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

cow stringtable

This commit is contained in:
Robin Appelman 2020-12-06 17:42:15 +01:00
commit 9f0acad361
7 changed files with 29 additions and 16 deletions

View file

@ -7,6 +7,7 @@ use crate::demo::packet::stringtable::{
};
use crate::demo::parser::ParseBitSkip;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use std::borrow::Cow;
use std::cmp::min;
#[derive(Debug)]
@ -50,7 +51,7 @@ impl<'a> Parse<'a> for CreateStringTableMessage<'a> {
let magic = table_data.read_string(Some(4))?;
if magic != "SNAP" {
return Err(ParseError::UnexpectedCompressionType(magic));
return Err(ParseError::UnexpectedCompressionType(magic.into_owned()));
}
let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?;
@ -234,19 +235,19 @@ fn read_table_entry<'a>(
// 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()?;
let rest_of_string: Cow<str> = stream.read()?;
Some(
match history
.get_history(index as usize)
.and_then(|entry| entry.text.as_ref())
{
Some(text) => String::from_utf8({
Some(text) => Cow::Owned(String::from_utf8({
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
},
)

View file

@ -4,6 +4,7 @@ use bitbuffer::{BitRead, LittleEndian};
use crate::demo::message::stringtable::StringTableMeta;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use std::borrow::{Borrow, Cow};
use std::cmp::min;
#[derive(BitRead, Clone, Copy, Debug)]
@ -78,13 +79,16 @@ impl<'a> ExtraData<'a> {
#[derive(Clone, Default)]
pub struct StringTableEntry<'a> {
pub text: Option<String>,
pub text: Option<Cow<'a, str>>,
pub extra_data: Option<ExtraData<'a>>,
}
impl StringTableEntry<'_> {
pub fn text(&self) -> &str {
self.text.as_ref().map(|s| s.as_str()).unwrap_or("")
self.text
.as_ref()
.map(|text| text.borrow())
.unwrap_or_default()
}
}

View file

@ -123,7 +123,10 @@ impl ClassList {
#[test]
fn test_classlist_sorted() {
let list = ClassList([0, 1, 5, 0, 0, 3, 0, 0, 0, 0]);
assert_eq!(list.sorted().collect::<Vec<_>>(), &[(Class::Sniper, 5), (Class::Medic, 3), (Class::Scout, 1)])
assert_eq!(
list.sorted().collect::<Vec<_>>(),
&[(Class::Sniper, 5), (Class::Medic, 3), (Class::Scout, 1)]
)
}
impl Index<Class> for ClassList {
@ -310,7 +313,7 @@ impl MessageHandler for Analyser {
match table {
"userinfo" => {
let _ = self.parse_user_info(
entry.text.as_ref().map(|s| s.as_str()),
entry.text.as_ref().map(|s| s.as_ref()),
entry.extra_data.as_ref().map(|data| data.data.clone()),
);
}

View file

@ -2,8 +2,10 @@ use crate::demo::gamevent::GameEventValueType;
use crate::demo::message::gameevent::GameEventTypeId;
use crate::demo::message::packetentities::EntityId;
use crate::demo::packet::datatable::{ClassId, SendTableName};
use bitbuffer::{BitError, FromUtf8Error};
use bitbuffer::BitError;
use err_derive::Error;
use std::str::Utf8Error;
use std::string::FromUtf8Error;
/// Errors that can occur during parsing
#[derive(Debug, Error)]
@ -11,7 +13,7 @@ pub enum ParseError {
#[error(display = "Error while reading bits from stream: {}", _0)]
ReadError(#[error(source, no_from)] BitError),
#[error(display = "Malformed utf8 while reading string")]
MalformedUTF8(#[error(source)] FromUtf8Error),
MalformedUTF8(#[error(source)] Utf8Error),
#[error(display = "Unexpected type of compressed data: {}", _0)]
UnexpectedCompressionType(String),
#[error(
@ -109,4 +111,10 @@ impl From<BitError> for ParseError {
}
}
impl From<FromUtf8Error> for ParseError {
fn from(err: FromUtf8Error) -> ParseError {
ParseError::MalformedUTF8(err.utf8_error())
}
}
pub type Result<T> = std::result::Result<T, ParseError>;

View file

@ -160,7 +160,7 @@ impl SendPropDefinition {
index: SendPropDefinitionIndex,
) -> ReadResult<Self> {
let prop_type = SendPropType::read(stream)?;
let name = stream.read_string(None)?.into();
let name = stream.read_string(None)?.to_string().into();
let flags = SendPropFlags::read(stream)?;
let mut table_name = None;
let mut element_count = None;