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