mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
cow stringtable
This commit is contained in:
parent
f9116ef9f7
commit
9f0acad361
7 changed files with 29 additions and 16 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -70,8 +70,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitbuffer"
|
name = "bitbuffer"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2b3cd4415fb790abfc898cd449f319029933a867462634dbd427c3f884ba6c5"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitbuffer_derive",
|
"bitbuffer_derive",
|
||||||
"err-derive",
|
"err-derive",
|
||||||
|
|
@ -82,8 +80,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitbuffer_derive"
|
name = "bitbuffer_derive"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f51dcbe693d21078994abd2afac5adc9bcc80fbdf80206ebdb33fec4a145693"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ name = "loop"
|
||||||
path = "src/bin/loop.rs"
|
path = "src/bin/loop.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitbuffer = "0.8"
|
#bitbuffer = "0.8"
|
||||||
|
bitbuffer = { version = "0.8", path = "../../bitbuffer"}
|
||||||
num_enum = "0.5"
|
num_enum = "0.5"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
enumflags2 = "0.6"
|
enumflags2 = "0.6"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use crate::demo::packet::stringtable::{
|
||||||
};
|
};
|
||||||
use crate::demo::parser::ParseBitSkip;
|
use crate::demo::parser::ParseBitSkip;
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -50,7 +51,7 @@ impl<'a> Parse<'a> for CreateStringTableMessage<'a> {
|
||||||
let magic = table_data.read_string(Some(4))?;
|
let magic = table_data.read_string(Some(4))?;
|
||||||
|
|
||||||
if magic != "SNAP" {
|
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)?;
|
let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?;
|
||||||
|
|
@ -234,19 +235,19 @@ fn read_table_entry<'a>(
|
||||||
// reuse from history
|
// reuse from history
|
||||||
let index: u16 = stream.read_sized(5)?;
|
let index: u16 = stream.read_sized(5)?;
|
||||||
let bytes_to_copy: u32 = 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(
|
Some(
|
||||||
match history
|
match history
|
||||||
.get_history(index as usize)
|
.get_history(index as usize)
|
||||||
.and_then(|entry| entry.text.as_ref())
|
.and_then(|entry| entry.text.as_ref())
|
||||||
{
|
{
|
||||||
Some(text) => String::from_utf8({
|
Some(text) => Cow::Owned(String::from_utf8({
|
||||||
text.bytes()
|
text.bytes()
|
||||||
.take(bytes_to_copy as usize)
|
.take(bytes_to_copy as usize)
|
||||||
.chain(rest_of_string.bytes())
|
.chain(rest_of_string.bytes())
|
||||||
.collect()
|
.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
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use bitbuffer::{BitRead, LittleEndian};
|
||||||
|
|
||||||
use crate::demo::message::stringtable::StringTableMeta;
|
use crate::demo::message::stringtable::StringTableMeta;
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
#[derive(BitRead, Clone, Copy, Debug)]
|
#[derive(BitRead, Clone, Copy, Debug)]
|
||||||
|
|
@ -78,13 +79,16 @@ impl<'a> ExtraData<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct StringTableEntry<'a> {
|
pub struct StringTableEntry<'a> {
|
||||||
pub text: Option<String>,
|
pub text: Option<Cow<'a, str>>,
|
||||||
pub extra_data: Option<ExtraData<'a>>,
|
pub extra_data: Option<ExtraData<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StringTableEntry<'_> {
|
impl StringTableEntry<'_> {
|
||||||
pub fn text(&self) -> &str {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,10 @@ impl ClassList {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_classlist_sorted() {
|
fn test_classlist_sorted() {
|
||||||
let list = ClassList([0, 1, 5, 0, 0, 3, 0, 0, 0, 0]);
|
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 {
|
impl Index<Class> for ClassList {
|
||||||
|
|
@ -310,7 +313,7 @@ impl MessageHandler for Analyser {
|
||||||
match table {
|
match table {
|
||||||
"userinfo" => {
|
"userinfo" => {
|
||||||
let _ = self.parse_user_info(
|
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()),
|
entry.extra_data.as_ref().map(|data| data.data.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ use crate::demo::gamevent::GameEventValueType;
|
||||||
use crate::demo::message::gameevent::GameEventTypeId;
|
use crate::demo::message::gameevent::GameEventTypeId;
|
||||||
use crate::demo::message::packetentities::EntityId;
|
use crate::demo::message::packetentities::EntityId;
|
||||||
use crate::demo::packet::datatable::{ClassId, SendTableName};
|
use crate::demo::packet::datatable::{ClassId, SendTableName};
|
||||||
use bitbuffer::{BitError, FromUtf8Error};
|
use bitbuffer::BitError;
|
||||||
use err_derive::Error;
|
use err_derive::Error;
|
||||||
|
use std::str::Utf8Error;
|
||||||
|
use std::string::FromUtf8Error;
|
||||||
|
|
||||||
/// Errors that can occur during parsing
|
/// Errors that can occur during parsing
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
@ -11,7 +13,7 @@ pub enum ParseError {
|
||||||
#[error(display = "Error while reading bits from stream: {}", _0)]
|
#[error(display = "Error while reading bits from stream: {}", _0)]
|
||||||
ReadError(#[error(source, no_from)] BitError),
|
ReadError(#[error(source, no_from)] BitError),
|
||||||
#[error(display = "Malformed utf8 while reading string")]
|
#[error(display = "Malformed utf8 while reading string")]
|
||||||
MalformedUTF8(#[error(source)] FromUtf8Error),
|
MalformedUTF8(#[error(source)] Utf8Error),
|
||||||
#[error(display = "Unexpected type of compressed data: {}", _0)]
|
#[error(display = "Unexpected type of compressed data: {}", _0)]
|
||||||
UnexpectedCompressionType(String),
|
UnexpectedCompressionType(String),
|
||||||
#[error(
|
#[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>;
|
pub type Result<T> = std::result::Result<T, ParseError>;
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ impl SendPropDefinition {
|
||||||
index: SendPropDefinitionIndex,
|
index: SendPropDefinitionIndex,
|
||||||
) -> ReadResult<Self> {
|
) -> ReadResult<Self> {
|
||||||
let prop_type = SendPropType::read(stream)?;
|
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 flags = SendPropFlags::read(stream)?;
|
||||||
let mut table_name = None;
|
let mut table_name = None;
|
||||||
let mut element_count = None;
|
let mut element_count = None;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue