mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
normalize prop definitions during flatening
This commit is contained in:
parent
35519d5fce
commit
0a34318c65
5 changed files with 98 additions and 72 deletions
|
|
@ -19,43 +19,43 @@ use tf_demo_parser::{Demo, DemoParser, MatchState, MessageType, MessageTypeAnaly
|
|||
|
||||
pub struct SendPropAnalyser;
|
||||
|
||||
// impl MessageHandler for SendPropAnalyser {
|
||||
// type Output = Vec<ParseSendTable>;
|
||||
//
|
||||
// fn does_handle(message_type: MessageType) -> bool {
|
||||
// false
|
||||
// }
|
||||
//
|
||||
// fn into_output(self, state: &ParserState) -> Self::Output {
|
||||
// state
|
||||
// .send_tables
|
||||
// .iter()
|
||||
// .map(|v| ParseSendTable {
|
||||
// name: v.name.clone(),
|
||||
// props: v.props.clone(),
|
||||
// needs_decoder: v.needs_decoder,
|
||||
// })
|
||||
// .collect()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn flatten_bench(input_file: &str, b: &mut Bencher) {
|
||||
// let file = fs::read(input_file).expect("Unable to read file");
|
||||
// let demo = Demo::new(&file);
|
||||
// let stream = demo.get_stream();
|
||||
// let (_, send_tables) = DemoParser::new_with_analyser(stream.clone(), SendPropAnalyser)
|
||||
// .parse()
|
||||
// .unwrap();
|
||||
// b.iter(|| {
|
||||
// let flat: Vec<_> = send_tables
|
||||
// .iter()
|
||||
// .map(|table| table.flatten_props(&send_tables))
|
||||
// .collect();
|
||||
// test::black_box(flat);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// #[bench]
|
||||
// fn sendprop_test_gully(b: &mut Bencher) {
|
||||
// flatten_bench("data/gully.dem", b);
|
||||
// }
|
||||
impl MessageHandler for SendPropAnalyser {
|
||||
type Output = Vec<ParseSendTable>;
|
||||
|
||||
fn does_handle(message_type: MessageType) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn into_output(self, state: &ParserState) -> Self::Output {
|
||||
state
|
||||
.send_tables
|
||||
.iter()
|
||||
.map(|v| ParseSendTable {
|
||||
name: v.name.clone(),
|
||||
props: v.raw_props.clone(),
|
||||
needs_decoder: v.needs_decoder,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_bench(input_file: &str, b: &mut Bencher) {
|
||||
let file = fs::read(input_file).expect("Unable to read file");
|
||||
let demo = Demo::new(&file);
|
||||
let stream = demo.get_stream();
|
||||
let (_, send_tables) = DemoParser::new_with_analyser(stream.clone(), SendPropAnalyser)
|
||||
.parse()
|
||||
.unwrap();
|
||||
b.iter(|| {
|
||||
let flat: Vec<_> = send_tables
|
||||
.iter()
|
||||
.map(|table| table.flatten_props(&send_tables))
|
||||
.collect();
|
||||
test::black_box(flat);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn sendprop_test_gully(b: &mut Bencher) {
|
||||
flatten_bench("data/gully.dem", b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use std::cmp::min;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(BitRead, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Display, FromStr)]
|
||||
|
|
@ -121,14 +122,14 @@ impl ParseSendTable {
|
|||
}
|
||||
|
||||
impl ParseSendTable {
|
||||
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Vec<RawSendPropDefinition> {
|
||||
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Result<Vec<SendPropDefinition>> {
|
||||
let mut flat = Vec::with_capacity(32);
|
||||
self.get_all_props(tables, &self.get_excludes(tables), &mut flat);
|
||||
self.get_all_props(tables, &self.get_excludes(tables), &mut flat)?;
|
||||
|
||||
// sort often changed props before the others
|
||||
let mut start = 0;
|
||||
for i in 0..flat.len() {
|
||||
if flat[i].flags.contains(SendPropFlag::ChangesOften) {
|
||||
if flat[i].changes_often {
|
||||
if i != start {
|
||||
flat.swap(i, start);
|
||||
}
|
||||
|
|
@ -136,7 +137,7 @@ impl ParseSendTable {
|
|||
}
|
||||
}
|
||||
|
||||
flat
|
||||
Ok(flat)
|
||||
}
|
||||
|
||||
fn get_excludes<'a>(&'a self, tables: &'a [ParseSendTable]) -> Vec<SendPropIdentifier> {
|
||||
|
|
@ -161,36 +162,40 @@ impl ParseSendTable {
|
|||
&self,
|
||||
tables: &[ParseSendTable],
|
||||
excludes: &[SendPropIdentifier],
|
||||
props: &mut Vec<RawSendPropDefinition>,
|
||||
) {
|
||||
props: &mut Vec<SendPropDefinition>,
|
||||
) -> Result<()> {
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_all_props_iterator_props(
|
||||
&self,
|
||||
tables: &[ParseSendTable],
|
||||
excludes: &[SendPropIdentifier],
|
||||
local_props: &mut Vec<RawSendPropDefinition>,
|
||||
props: &mut Vec<RawSendPropDefinition>,
|
||||
) {
|
||||
local_props: &mut Vec<SendPropDefinition>,
|
||||
props: &mut Vec<SendPropDefinition>,
|
||||
) -> Result<()> {
|
||||
self.props
|
||||
.iter()
|
||||
.filter(|prop| !prop.is_exclude())
|
||||
.filter(|prop| !excludes.iter().any(|exclude| *exclude == prop.identifier()))
|
||||
.for_each(|prop| {
|
||||
.map(|prop| {
|
||||
if let Some(table) = prop.get_data_table(tables) {
|
||||
if prop.flags.contains(SendPropFlag::Collapsible) {
|
||||
table.get_all_props_iterator_props(tables, excludes, local_props, props);
|
||||
table.get_all_props_iterator_props(tables, excludes, local_props, props)?;
|
||||
} else {
|
||||
table.get_all_props(tables, excludes, props);
|
||||
table.get_all_props(tables, excludes, props)?;
|
||||
}
|
||||
} else {
|
||||
local_props.push(prop.clone());
|
||||
local_props.push(SendPropDefinition::try_from(prop)?);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.collect::<Result<()>>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +203,7 @@ impl ParseSendTable {
|
|||
pub struct SendTable {
|
||||
pub name: SendTableName,
|
||||
pub needs_decoder: bool,
|
||||
pub raw_props: Vec<RawSendPropDefinition>,
|
||||
pub flattened_props: Vec<SendPropDefinition>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@ use crate::demo::packet::datatable::{
|
|||
};
|
||||
use crate::demo::packet::stringtable::StringTableEntry;
|
||||
|
||||
use crate::demo::sendprop::{SendProp, SendPropDefinition};
|
||||
use crate::demo::sendprop::SendProp;
|
||||
use crate::nullhasher::NullHasherBuilder;
|
||||
use crate::{Result, Stream};
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct DemoMeta {
|
||||
|
|
@ -106,25 +105,23 @@ impl<'a> ParserState {
|
|||
let flat_props: Vec<_> = parse_tables
|
||||
.iter()
|
||||
.map(|table| table.flatten_props(&parse_tables))
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let mut send_tables: FnvHashMap<SendTableName, SendTable> = parse_tables
|
||||
.into_iter()
|
||||
.zip(flat_props.into_iter())
|
||||
.map(|(parse_table, flat)| {
|
||||
Ok((
|
||||
(
|
||||
parse_table.name.clone(),
|
||||
SendTable {
|
||||
name: parse_table.name,
|
||||
needs_decoder: parse_table.needs_decoder,
|
||||
flattened_props: flat
|
||||
.into_iter()
|
||||
.map(|raw| SendPropDefinition::try_from(raw))
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?,
|
||||
raw_props: parse_table.props,
|
||||
flattened_props: flat,
|
||||
},
|
||||
))
|
||||
)
|
||||
})
|
||||
.collect::<Result<_>>()?;
|
||||
.collect();
|
||||
|
||||
self.server_classes = server_classes;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use std::convert::{TryFrom, TryInto};
|
|||
use fnv::FnvHasher;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::num::NonZeroU64;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(
|
||||
|
|
@ -347,16 +348,18 @@ impl FloatDefinition {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SendPropDefinition {
|
||||
pub changes_often: bool,
|
||||
pub identifier: SendPropIdentifier,
|
||||
pub parse_definition: SendPropParseDefinition,
|
||||
}
|
||||
|
||||
impl TryFrom<RawSendPropDefinition> for SendPropDefinition {
|
||||
impl TryFrom<&RawSendPropDefinition> for SendPropDefinition {
|
||||
type Error = MalformedSendPropDefinitionError;
|
||||
|
||||
fn try_from(definition: RawSendPropDefinition) -> std::result::Result<Self, Self::Error> {
|
||||
let parse_definition = (&definition).try_into()?;
|
||||
fn try_from(definition: &RawSendPropDefinition) -> std::result::Result<Self, Self::Error> {
|
||||
let parse_definition = definition.try_into()?;
|
||||
Ok(SendPropDefinition {
|
||||
changes_often: definition.flags.contains(SendPropFlag::ChangesOften),
|
||||
parse_definition,
|
||||
identifier: definition.identifier(),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,34 +1,50 @@
|
|||
use std::fs;
|
||||
use test_case::test_case;
|
||||
|
||||
use fnv::FnvHashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName, ServerClass};
|
||||
use tf_demo_parser::demo::parser::MessageHandler;
|
||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropName};
|
||||
use tf_demo_parser::{Demo, DemoParser, MessageType, ParserState};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SendPropAnalyser {
|
||||
tables: Vec<ParseSendTable>,
|
||||
prop_names: FnvHashMap<SendPropIdentifier, (SendTableName, SendPropName)>,
|
||||
}
|
||||
|
||||
impl SendPropAnalyser {
|
||||
pub fn new() -> Self {
|
||||
SendPropAnalyser { tables: Vec::new() }
|
||||
SendPropAnalyser::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl MessageHandler for SendPropAnalyser {
|
||||
type Output = Vec<ParseSendTable>;
|
||||
type Output = (
|
||||
Vec<ParseSendTable>,
|
||||
FnvHashMap<SendPropIdentifier, (SendTableName, SendPropName)>,
|
||||
);
|
||||
|
||||
fn does_handle(_message_type: MessageType) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn handle_data_tables(&mut self, tables: &[ParseSendTable], _server_classes: &[ServerClass]) {
|
||||
for table in tables {
|
||||
for prop_def in &table.props {
|
||||
self.prop_names.insert(
|
||||
prop_def.identifier(),
|
||||
(prop_def.owner_table.clone(), prop_def.name.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.tables = tables.to_vec()
|
||||
}
|
||||
|
||||
fn into_output(self, _state: &ParserState) -> Self::Output {
|
||||
self.tables
|
||||
(self.tables, self.prop_names)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +52,7 @@ impl MessageHandler for SendPropAnalyser {
|
|||
fn flatten_test(input_file: &str, snapshot_file: &str) {
|
||||
let file = fs::read(input_file).expect("Unable to read file");
|
||||
let demo = Demo::new(&file);
|
||||
let (_, send_tables) =
|
||||
let (_, (send_tables, prop_names)) =
|
||||
DemoParser::new_with_analyser(demo.get_stream(), SendPropAnalyser::new())
|
||||
.parse()
|
||||
.expect("Failed to parse");
|
||||
|
|
@ -47,8 +63,12 @@ fn flatten_test(input_file: &str, snapshot_file: &str) {
|
|||
table.name.clone(),
|
||||
table
|
||||
.flatten_props(&send_tables)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|prop| format!("{}.{}", prop.owner_table, prop.name))
|
||||
.map(|prop| {
|
||||
let (table_name, prop_name) = &prop_names[&prop.identifier];
|
||||
format!("{}.{}", table_name, prop_name)
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue