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

cache flat props

This commit is contained in:
Robin Appelman 2019-08-10 20:36:32 +02:00
commit 164f88a32a
4 changed files with 54 additions and 22 deletions

View file

@ -9,7 +9,7 @@ use std::fs;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use tf_demo_parser::{Demo, DemoParser, MatchState, MessageTypeAnalyser, MessageType, ParserState}; use tf_demo_parser::{Demo, DemoParser, MatchState, MessageTypeAnalyser, MessageType, ParserState};
use tf_demo_parser::demo::packet::datatable::{SendTable, SendTableName}; use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
use tf_demo_parser::demo::packet::stringtable::StringTableEntry; use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
use tf_demo_parser::demo::message::Message; use tf_demo_parser::demo::message::Message;
use tf_demo_parser::demo::sendprop::SendPropDefinition; use tf_demo_parser::demo::sendprop::SendPropDefinition;
@ -20,7 +20,7 @@ use test::Bencher;
pub struct SendPropAnalyser; pub struct SendPropAnalyser;
impl MessageHandler for SendPropAnalyser { impl MessageHandler for SendPropAnalyser {
type Output = Vec<SendTable>; type Output = Vec<ParseSendTable>;
fn does_handle(message_type: MessageType) -> bool { fn does_handle(message_type: MessageType) -> bool {
false false
@ -31,7 +31,11 @@ impl MessageHandler for SendPropAnalyser {
fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {} fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {}
fn get_output(self, state: ParserState) -> Self::Output { fn get_output(self, state: ParserState) -> Self::Output {
state.send_tables.into_iter().map(|(_k, v)| v).collect() state.send_tables.into_iter().map(|(_k, v)| ParseSendTable {
name: v.name,
props: v.props,
needs_decoder: v.needs_decoder
}).collect()
} }
} }

View file

@ -5,6 +5,8 @@ use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
use std::fmt; use std::fmt;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::rc::Rc; use std::rc::Rc;
use std::cell::{Cell, RefCell};
use std::ops::Deref;
#[derive(BitRead, Debug)] #[derive(BitRead, Debug)]
pub struct ServerClass { pub struct ServerClass {
@ -41,14 +43,13 @@ impl BitRead<LittleEndian> for SendTableName {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct SendTable { pub struct ParseSendTable {
pub name: SendTableName, pub name: SendTableName,
pub props: Vec<SendPropDefinition>, pub props: Vec<SendPropDefinition>,
pub needs_decoder: bool, pub needs_decoder: bool,
pub flattened_props: Option<Vec<SendPropDefinition>>,
} }
impl Parse for SendTable { impl Parse for ParseSendTable {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> { fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let needs_decoder = stream.read()?; let needs_decoder = stream.read()?;
let raw_name: String = stream.read()?; let raw_name: String = stream.read()?;
@ -83,17 +84,16 @@ impl Parse for SendTable {
} }
} }
Ok(SendTable { Ok(ParseSendTable {
name, name,
flattened_props: None,
needs_decoder, needs_decoder,
props, props,
}) })
} }
} }
impl SendTable { impl ParseSendTable {
pub fn flatten_props<'a>(&'a self, tables: &'a [SendTable]) -> Vec<&'a SendPropDefinition> { pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Vec<SendPropDefinition> {
let mut flat = Vec::new(); let mut flat = Vec::new();
self.get_all_props(tables, &self.get_excludes(tables), &mut flat); self.get_all_props(tables, &self.get_excludes(tables), &mut flat);
@ -108,10 +108,10 @@ impl SendTable {
} }
} }
flat flat.into_iter().map(|prop| prop.clone()).collect()
} }
fn get_excludes<'a>(&'a self, tables: &'a [SendTable]) -> Vec<Exclude<'a>> { fn get_excludes<'a>(&'a self, tables: &'a [ParseSendTable]) -> Vec<Exclude<'a>> {
let mut excludes = Vec::new(); let mut excludes = Vec::new();
for prop in self.props.iter() { for prop in self.props.iter() {
@ -131,14 +131,14 @@ impl SendTable {
} }
// TODO: below is a direct port from the js which is a direct port from C++ and not very optimal // TODO: below is a direct port from the js which is a direct port from C++ and not very optimal
fn get_all_props<'a>(&'a self, tables: &'a [SendTable], excludes: &[Exclude], props: &mut Vec<&'a SendPropDefinition>) { fn get_all_props<'a>(&'a self, tables: &'a [ParseSendTable], excludes: &[Exclude], props: &mut Vec<&'a SendPropDefinition>) {
let mut local_props = Vec::new(); let mut local_props = Vec::new();
self.get_all_props_iterator_props(tables, excludes, &mut local_props, props); self.get_all_props_iterator_props(tables, excludes, &mut local_props, props);
props.extend_from_slice(&local_props); props.extend_from_slice(&local_props);
} }
fn get_all_props_iterator_props<'a>(&'a self, tables: &'a [SendTable], excludes: &[Exclude], local_props: &mut Vec<&'a SendPropDefinition>, props: &mut Vec<&'a SendPropDefinition>) { fn get_all_props_iterator_props<'a>(&'a self, tables: &'a [ParseSendTable], excludes: &[Exclude], local_props: &mut Vec<&'a SendPropDefinition>, props: &mut Vec<&'a SendPropDefinition>) {
for prop in self.props.iter() { for prop in self.props.iter() {
if prop.is_exclude() { if prop.is_exclude() {
continue; continue;
@ -175,6 +175,14 @@ impl<'a> Exclude<'a> {
} }
} }
#[derive(Debug)]
pub struct SendTable {
pub name: SendTableName,
pub props: Vec<SendPropDefinition>,
pub needs_decoder: bool,
pub flattened_props: Vec<SendPropDefinition>,
}
#[derive(Debug)] #[derive(Debug)]
pub struct DataTablePacket { pub struct DataTablePacket {
pub tick: u32, pub tick: u32,
@ -188,12 +196,28 @@ impl Parse for DataTablePacket {
let len = stream.read_int::<usize>(32)?; let len = stream.read_int::<usize>(32)?;
let mut packet_data = stream.read_bits(len * 8)?; let mut packet_data = stream.read_bits(len * 8)?;
let mut tables = Vec::new(); let mut parse_tables = Vec::new();
while packet_data.read_bool()? { while packet_data.read_bool()? {
let table = SendTable::parse(&mut packet_data, state)?; let table = ParseSendTable::parse(&mut packet_data, state)?;
tables.push(table); parse_tables.push(table);
} }
let flat_props: Vec<_> = parse_tables.iter()
.map(|table| table.flatten_props(&parse_tables))
.collect();
let tables = parse_tables.into_iter()
.zip(flat_props.into_iter())
.map(|(parse_table, flat)| {
SendTable {
name: parse_table.name,
props: parse_table.props,
needs_decoder: parse_table.needs_decoder,
flattened_props: flat,
}
})
.collect();
// TODO linked tables? // TODO linked tables?
let server_class_count = packet_data.read_int(16)?; let server_class_count = packet_data.read_int(16)?;

View file

@ -4,7 +4,7 @@ use enumflags2_derive::EnumFlags;
use crate::{ReadResult, Result, Stream, Parse}; use crate::{ReadResult, Result, Stream, Parse};
use super::packet::datatable::SendTable; use super::packet::datatable::ParseSendTable;
use super::vector::{Vector, VectorXY}; use super::vector::{Vector, VectorXY};
use crate::demo::packet::datatable::SendTableName; use crate::demo::packet::datatable::SendTableName;
@ -41,7 +41,7 @@ impl SendPropDefinition {
/// Get the refered data table /// Get the refered data table
/// ///
/// Note that this is not the owner table /// Note that this is not the owner table
pub fn get_data_table<'a>(&self, tables: &'a [SendTable]) -> Option<&'a SendTable> { pub fn get_data_table<'a>(&self, tables: &'a [ParseSendTable]) -> Option<&'a ParseSendTable> {
self.table_name.as_ref() self.table_name.as_ref()
.and_then(|name| tables.iter().find(|table| table.name == *name)) .and_then(|name| tables.iter().find(|table| table.name == *name))
} }

View file

@ -6,7 +6,7 @@ use std::fs;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use tf_demo_parser::{Demo, DemoParser, MatchState, MessageTypeAnalyser, MessageType, ParserState}; use tf_demo_parser::{Demo, DemoParser, MatchState, MessageTypeAnalyser, MessageType, ParserState};
use tf_demo_parser::demo::packet::datatable::{SendTable, SendTableName}; use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
use tf_demo_parser::demo::packet::stringtable::StringTableEntry; use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
use tf_demo_parser::demo::message::Message; use tf_demo_parser::demo::message::Message;
use tf_demo_parser::demo::sendprop::SendPropDefinition; use tf_demo_parser::demo::sendprop::SendPropDefinition;
@ -16,7 +16,7 @@ use tf_demo_parser::demo::parser::MessageHandler;
pub struct SendPropAnalyser; pub struct SendPropAnalyser;
impl MessageHandler for SendPropAnalyser { impl MessageHandler for SendPropAnalyser {
type Output = Vec<SendTable>; type Output = Vec<ParseSendTable>;
fn does_handle(message_type: MessageType) -> bool { fn does_handle(message_type: MessageType) -> bool {
false false
@ -27,7 +27,11 @@ impl MessageHandler for SendPropAnalyser {
fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {} fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {}
fn get_output(self, state: ParserState) -> Self::Output { fn get_output(self, state: ParserState) -> Self::Output {
state.send_tables.into_iter().map(|(_k, v)| v).collect() state.send_tables.into_iter().map(|(_k, v)| ParseSendTable {
name: v.name,
props: v.props,
needs_decoder: v.needs_decoder
}).collect()
} }
} }