1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-04 02:24:12 +02:00
This commit is contained in:
Robin Appelman 2019-03-02 22:33:22 +01:00
commit f2650dc32f
19 changed files with 3614 additions and 2210 deletions

View file

@ -1,11 +1,13 @@
use std::collections::HashMap;
use arraydeque::{ArrayDeque, Wrapping};
use bitstream_reader::{BitRead, BitReadSized, BitStream, LittleEndian, BitBuffer};
use bitstream_reader::{BitBuffer, BitRead, BitReadSized, BitStream, LittleEndian};
use snap::Decoder;
use crate::demo::packet::stringtable::{
ExtraData, FixedUserdataSize, StringTable, StringTableEntry,
};
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use crate::demo::packet::stringtable::{ExtraData, FixedUserdataSize, StringTable, StringTableEntry};
use num_traits::{PrimInt, Unsigned};
#[derive(Debug)]
@ -55,12 +57,14 @@ impl Parse for CreateStringTableMessage {
let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?;
let mut decoder = Decoder::new();
let decompressed_data = decoder.decompress_vec(&compressed_data).map_err(ParseError::from)?;
let decompressed_data = decoder
.decompress_vec(&compressed_data)
.map_err(ParseError::from)?;
if decompressed_data.len() != decompressed_size as usize {
return Err(ParseError::UnexpectedDecompressedSize {
expected: decompressed_size,
size: decompressed_data.len() as u32
size: decompressed_data.len() as u32,
});
}
@ -73,7 +77,8 @@ impl Parse for CreateStringTableMessage {
fixed_userdata_size,
};
let entries = parse_string_table_entries(&mut table_data, &table_meta, entity_count, &Vec::new())?;
let entries =
parse_string_table_entries(&mut table_data, &table_meta, entity_count, &Vec::new())?;
let mut entries: Vec<(u16, StringTableEntry)> = entries.into_iter().collect();
// verify that there are no holes in our indexes
@ -93,9 +98,7 @@ impl Parse for CreateStringTableMessage {
compressed,
name,
};
Ok(CreateStringTableMessage {
table
})
Ok(CreateStringTableMessage { table })
}
}
@ -115,14 +118,16 @@ impl Parse for UpdateStringTableMessage {
let mut data = stream.read_bits(len)?;
let entries = match state.string_tables.get(table_id as usize) {
Some(table) => parse_string_table_entries(&mut data, &table.get_table_meta(), changed, &table.entries),
None => return Err(ParseError::StringTableNotFound(table_id))
Some(table) => parse_string_table_entries(
&mut data,
&table.get_table_meta(),
changed,
&table.entries,
),
None => return Err(ParseError::StringTableNotFound(table_id)),
}?;
Ok(UpdateStringTableMessage {
table_id,
entries,
})
Ok(UpdateStringTableMessage { table_id, entries })
}
}
@ -147,17 +152,22 @@ fn parse_string_table_entries(
last_entry = index as i16;
let value = if stream.read()? { // set value
if stream.read()? { // reuse from history
let value = if stream.read()? {
// set value
if stream.read()? {
// reuse from history
let index: u16 = stream.read_sized(5)?;
let bytes_to_copy: u32 = stream.read_sized(5)?;
let rest_of_string: String = stream.read()?;
Some(match history.get(index as usize) {
Some(text) => String::from_utf8({
text.bytes().take(bytes_to_copy as usize).chain(rest_of_string.bytes()).collect()
text.bytes()
.take(bytes_to_copy as usize)
.chain(rest_of_string.bytes())
.collect()
})?,
None => rest_of_string // best guess, happens in some pov demos but only for unimportant tables it seems
None => rest_of_string, // best guess, happens in some pov demos but only for unimportant tables it seems
})
} else {
Some(stream.read()?)
@ -176,7 +186,8 @@ fn parse_string_table_entries(
})
} else {
None
}.map(|stream| ExtraData {
}
.map(|stream| ExtraData {
len: stream.bit_len() as u16 / 8,
data: stream,
});
@ -193,7 +204,7 @@ fn parse_string_table_entries(
None => StringTableEntry {
text: value.unwrap_or_default(),
extra_data: user_data,
}
},
};
// optimize: any way to get rid of the clone here?
// `entries` always outlives `history` without reallocation
@ -225,4 +236,4 @@ pub fn read_var_int(stream: &mut Stream) -> ReadResult<u32> {
pub fn log_base2<T: PrimInt + Unsigned>(num: T) -> u32 {
(std::mem::size_of::<T>() as u32 * 8 - 1) - num.leading_zeros()
}
}