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

update to new bitreader

This commit is contained in:
Robin Appelman 2019-02-28 21:55:53 +01:00
commit e7b9f5ecbb
25 changed files with 378 additions and 590 deletions

View file

@ -1,62 +1,23 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
//use crate::test::test_parse;
use bitstream_reader::{BitRead, LittleEndian};
#[derive(Debug, PartialEq)]
use crate::{Parse, ParseError, ParserState, Result, Stream};
#[derive(BitRead, Debug, PartialEq)]
pub struct Header {
#[size = 8]
pub demo_type: String,
pub version: u32,
pub protocol: u32,
#[size = 260]
pub server: String,
#[size = 260]
pub nick: String,
#[size = 260]
pub map: String,
#[size = 260]
pub game: String,
pub duration: f32,
pub ticks: u32,
pub frames: u32,
pub sigon: u32,
}
impl<'a> Parse<'a> for Header {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Header> {
Ok(Header {
demo_type: stream.read_string(Some(8))?,
version: stream.read(32)?,
protocol: stream.read(32)?,
server: stream.read_string(Some(260))?,
nick: stream.read_string(Some(260))?,
map: stream.read_string(Some(260))?,
game: stream.read_string(Some(260))?,
duration: stream.read_float()?,
ticks: stream.read(32)?,
frames: stream.read(32)?,
sigon: stream.read(32)?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream
.skip(8 * 8 + (32 * 2) + (260 * 8 * 4) + (32 * 4))
.map_err(ParseError::from)
}
}
//#[test]
//fn test_header() {
// test_parse(
// "data/small.dem",
// Header {
// demo_type: "HL2DEMO".to_owned(),
// version: 3,
// protocol: 24,
// server: "localhost:27015".to_owned(),
// nick: "Icewind | demos.tf".to_owned(),
// map: "cp_gullywash".to_owned(),
// game: "tf".to_owned(),
// duration: 1.7249999,
// ticks: 115,
// frames: 111,
// sigon: 218908,
// },
// 0,
// );
//}
}

View file

@ -0,0 +1,93 @@
/// Messages that consists only of primitives and string and can be derived
use bitstream_reader::BitRead;
use std::collections::HashMap;
#[derive(BitRead, Debug)]
pub struct FileMessage {
pub transfer_id: u32,
pub file_name: String,
pub requested: bool,
}
#[derive(BitRead, Debug)]
pub struct NetTickMessage {
pub tick: u32,
pub frame_time: u16,
pub std_dev: u16,
}
#[derive(BitRead, Debug)]
pub struct StringCmdMessage {
pub command: String
}
#[derive(BitRead, Debug)]
pub struct SigOnStateMessage {
pub state: u8,
pub count: u32,
}
#[derive(BitRead, Debug)]
pub struct PrintMessage {
pub value: String
}
#[derive(BitRead, Debug)]
pub struct ServerInfoMessage {
pub version: u16,
pub server_count: u32,
pub stv: bool,
pub dedicated: bool,
pub max_crc: u32,
pub max_classes: u16,
pub map_hash: u128,
pub player_count: u8,
pub max_player_count: u8,
pub interval_per_tick: f32,
#[size = 1]
pub platform: String,
pub game: String,
pub map: String,
pub skybox: String,
pub server_name: String,
pub replay: bool,
}
#[derive(BitRead, Debug)]
pub struct SetPauseMessage {
pub pause: bool
}
#[derive(BitRead, Debug)]
pub struct SetViewMessage {
#[size = 11]
pub index: u16
}
#[derive(BitRead, Debug)]
pub struct FixAngleMessage {
pub relative: bool,
pub x: u16,
pub y: u16,
pub z: u16,
}
#[derive(BitRead, Debug)]
pub struct PreFetchMessage {
#[size = 14]
pub index: u16
}
#[derive(BitRead, Debug)]
pub struct GetCvarMessage {
pub cookie: u32,
pub value: String,
}
#[derive(BitRead, Debug)]
pub struct SetConVarMessage {
#[size_bits = 8]
vars: HashMap<String, String>
}

51
src/demo/message/mod.rs Normal file
View file

@ -0,0 +1,51 @@
use enum_primitive_derive::Primitive;
use num_traits::FromPrimitive;
pub use generated::*;
use crate::{Parse, ParseError, ParserState, Result, Stream};
mod generated;
#[derive(Primitive, Debug)]
pub enum MessageType {
File = 2,
NetTick = 3,
StringCmd = 4,
SetConVar = 5,
SigOnState = 6,
Print = 7,
ServerInfo = 8,
ClassInfo = 10,
SetPause = 11,
CreateStringTable = 12,
UpdateStringTable = 13,
VoiceInit = 14,
VoiceData = 15,
ParseSounds = 17,
SetView = 18,
FixAngle = 19,
BspDecal = 21,
UserMessage = 23,
EntityMessage = 24,
GameEvent = 25,
PacketEntities = 26,
TempEntities = 27,
PreFetch = 28,
Menu = 29,
GameEventList = 30,
GetCvarValue = 31,
CmdKeyValues = 32,
}
impl Parse for MessageType {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let raw = stream.read_int(6)?;
let prop_type: Option<MessageType> = MessageType::from_u8(raw);
prop_type.ok_or(ParseError::InvalidMessageType(raw))
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(6).map_err(ParseError::from)
}
}

View file

@ -1,41 +1,31 @@
use bitstream_reader::{BitBuffer, BitStream, LittleEndian, NonPadded};
use crate::{ParserState, Parse, ParseError, Result};
use rentals::OwnedBuffer;
use bitstream_reader::{BitBuffer, BitStream, LittleEndian};
use crate::{Parse, ParseError, ParserState, Result};
pub mod gamevent;
pub mod header;
pub mod message;
pub mod packet;
pub mod parser;
pub mod sendprop;
pub mod vector;
pub type Buffer<'a> = BitBuffer<'a, LittleEndian, NonPadded>;
pub type Stream<'a> = BitStream<'a, LittleEndian, NonPadded>;
rental! {
mod rentals {
use super::*;
#[rental_mut(covariant)]
pub struct OwnedBuffer {
source_vec: Vec<u8>,
stream: Buffer<'source_vec>,
}
}
}
pub type Buffer = BitBuffer<LittleEndian>;
pub type Stream = BitStream<LittleEndian>;
pub struct Demo {
data: OwnedBuffer,
stream: Stream,
}
impl Demo {
pub fn new(vec: Vec<u8>) -> Self {
let data = OwnedBuffer::new(vec, |bytes| BitBuffer::new(bytes, LittleEndian));
Demo { data }
let data = Buffer::new(vec, LittleEndian);
let stream = Stream::new(data);
Demo { stream }
}
/// Get a new stream with the data of the demo
pub fn get_stream(&self) -> Stream {
BitStream::new(self.data.suffix().clone(), None, None)
self.stream.clone()
}
}
}

View file

@ -1,4 +1,6 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use bitstream_reader::{BitRead, LittleEndian};
use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
#[derive(Debug)]
pub struct ConsoleCmdPacket {
@ -6,21 +8,12 @@ pub struct ConsoleCmdPacket {
command: String,
}
impl<'a> Parse<'a> for ConsoleCmdPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let tick = stream.read(32)?;
let len = stream.read::<usize>(32)?;
impl BitRead<LittleEndian> for ConsoleCmdPacket {
fn read(stream: &mut Stream) -> ReadResult<Self> {
let tick = stream.read_int(32)?;
let len = stream.read_int::<usize>(32)?;
let mut packet_data = stream.read_bits(len * 8)?;
let command = packet_data.read_string(None)?;
Ok(ConsoleCmdPacket {
tick,
command,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32)?;
let len = stream.read::<usize>(32)?;
stream.skip(len * 8).map_err(ParseError::from)
Ok(ConsoleCmdPacket { tick, command })
}
}

View file

@ -1,4 +1,6 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use bitstream_reader::{BitRead, LittleEndian};
use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropType};
#[derive(Debug)]
@ -23,32 +25,39 @@ pub struct DataTablePacket {
server_classes: Vec<ServerClass>,
}
impl<'a> Parse<'a> for DataTablePacket {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
let tick = stream.read(32)?;
impl Parse for DataTablePacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let tick = stream.read()?;
let start = stream.pos();
let len = stream.read::<usize>(32)?;
let len = stream.read_int::<usize>(32)?;
let mut packet_data = stream.read_bits(len * 8)?;
let mut tables = vec![];
while packet_data.read_bool()? {
let needs_decoder = packet_data.read_bool()?;
let name = packet_data.read_string(None)?;
let prop_count = packet_data.read(10)?;
let prop_count = packet_data.read_int(10)?;
let mut array_element_prop = None;
let mut props = Vec::with_capacity(prop_count);
for i in 0..prop_count {
let prop: SendPropDefinition = SendPropDefinition::parse(&mut packet_data, state, name.clone())?;
let prop: SendPropDefinition =
SendPropDefinition::read(&mut packet_data, name.clone())?;
if prop.flags.contains(SendPropFlag::InsideArray) {
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
return Err(ParseError::InvalidSendPropArray("Array contents can't have the 'ChangesOften' flag".to_owned()));
if array_element_prop.is_some()
|| prop.flags.contains(SendPropFlag::ChangesOften)
{
return Err(ParseError::InvalidSendPropArray(
"Array contents can't have the 'ChangesOften' flag".to_owned(),
));
}
array_element_prop = Some(prop);
} else if let Some(array_element) = array_element_prop {
if prop.prop_type != SendPropType::Array {
return Err(ParseError::InvalidSendPropArray("Array contents can without array".to_owned()));
return Err(ParseError::InvalidSendPropArray(
"Array contents can without array".to_owned(),
));
}
array_element_prop = None;
props.push(prop.with_array_property(array_element));
@ -68,10 +77,10 @@ impl<'a> Parse<'a> for DataTablePacket {
// TODO linked tables?
let server_class_count = packet_data.read(16)?;
let server_class_count = packet_data.read_int(16)?;
let mut server_classes = Vec::with_capacity(server_class_count);
for i in 0..server_class_count {
let id = packet_data.read(16)?;
let id = packet_data.read_int(16)?;
let name = packet_data.read_string(None)?;
let data_table = packet_data.read_string(None)?;
server_classes.push(ServerClass {
@ -91,10 +100,4 @@ impl<'a> Parse<'a> for DataTablePacket {
})
}
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32)?;
let len = stream.read::<usize>(32)?;
stream.skip(len * 8).map_err(ParseError::from)
}
}
}

View file

@ -1,5 +1,5 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use crate::demo::vector::Vector;
use crate::{Parse, ParseError, ParserState, Result, Stream};
#[derive(Debug)]
pub struct Message;
@ -16,10 +16,10 @@ pub struct MessagePacket {
flags: u32, // TODO
}
impl<'a> Parse<'a> for MessagePacket {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
let tick = stream.read(32)?;
let flags = stream.read(32)?;
impl Parse for MessagePacket {
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
let tick = stream.read_int(32)?;
let flags = stream.read_int(32)?;
let view_origin_1 = Vector::parse(stream, state)?;
let view_angle_1 = Vector::parse(stream, state)?;
@ -28,9 +28,9 @@ impl<'a> Parse<'a> for MessagePacket {
let view_angles = (Vector::parse(stream, state)?, view_angle_1);
let local_view_angles = (Vector::parse(stream, state)?, local_view_angle_1);
let sequence_in = stream.read(32)?;
let sequence_out = stream.read(32)?;
let length: usize = stream.read(32)?;
let sequence_in = stream.read_int(32)?;
let sequence_out = stream.read_int(32)?;
let length: usize = stream.read_int(32)?;
let mut packet_data = stream.read_bits(length * 8)?;
let messages = vec![];
@ -56,7 +56,7 @@ impl<'a> Parse<'a> for MessagePacket {
}
let _ = stream.skip(32 * 2)?;
let length: usize = stream.read::<usize>(32)?;
let length: usize = stream.read_int::<usize>(32)?;
stream.skip(length * 8).map_err(ParseError::from)
}
}
}

View file

@ -1,3 +1,4 @@
use bitstream_reader::{BitRead, LittleEndian};
use enum_primitive_derive::Primitive;
use num_traits::FromPrimitive;
@ -12,15 +13,15 @@ use self::synctick::SyncTickPacket;
use self::usercmd::UserCmdPacket;
pub mod consolecmd;
pub mod datatable;
pub mod message;
pub mod stop;
pub mod stringtable;
pub mod synctick;
pub mod usercmd;
pub mod datatable;
pub mod message;
#[derive(Debug)]
pub enum Packet<'a> {
pub enum Packet {
Sigon(MessagePacket),
Message(MessagePacket),
SyncTick(SyncTickPacket),
@ -28,10 +29,11 @@ pub enum Packet<'a> {
UserCmd(UserCmdPacket),
DataTables(DataTablePacket),
Stop(StopPacket),
StringTables(StringTablePacket<'a>),
StringTables(StringTablePacket),
}
#[derive(Primitive, Debug)]
#[derive(BitRead, Primitive, Debug)]
#[discriminant_bits = 8]
pub enum PacketType {
Sigon = 1,
Message = 2,
@ -43,21 +45,9 @@ pub enum PacketType {
StringTables = 8,
}
impl Parse<'_> for PacketType {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let raw = stream.read(8)?;
let prop_type: Option<PacketType> = PacketType::from_u8(raw);
prop_type.ok_or(ParseError::InvalidPacketType(raw))
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(8).map_err(ParseError::from)
}
}
impl<'a> Parse<'a> for Packet<'a> {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
let packet_type = PacketType::parse(stream, state)?;
impl Parse for Packet {
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
let packet_type = PacketType::read(stream)?;
Ok(match packet_type {
PacketType::Sigon => Packet::Sigon(MessagePacket::parse(stream, state)?),
PacketType::Message => Packet::Message(MessagePacket::parse(stream, state)?),
@ -66,22 +56,9 @@ impl<'a> Parse<'a> for Packet<'a> {
PacketType::UserCmd => Packet::UserCmd(UserCmdPacket::parse(stream, state)?),
PacketType::DataTables => Packet::DataTables(DataTablePacket::parse(stream, state)?),
PacketType::Stop => Packet::Stop(StopPacket::parse(stream, state)?),
PacketType::StringTables => Packet::StringTables(StringTablePacket::parse(stream, state)?),
PacketType::StringTables => {
Packet::StringTables(StringTablePacket::parse(stream, state)?)
}
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let packet_type = PacketType::parse(stream, &ParserState::new(&stream))?;
dbg!(&packet_type);
match packet_type {
PacketType::Sigon => MessagePacket::skip(stream),
PacketType::Message => MessagePacket::skip(stream),
PacketType::SyncTick => SyncTickPacket::skip(stream),
PacketType::ConsoleCmd => ConsoleCmdPacket::skip(stream),
PacketType::UserCmd => UserCmdPacket::skip(stream),
PacketType::DataTables => DataTablePacket::skip(stream),
PacketType::Stop => StopPacket::skip(stream),
PacketType::StringTables => StringTablePacket::skip(stream),
}
}
}

View file

@ -1,14 +1,12 @@
use crate::{Parse, ParserState, Result, Stream};
use bitstream_reader::{BitRead, LittleEndian};
use crate::{Parse, ParserState, Result, Stream, ReadResult};
#[derive(Debug)]
pub struct StopPacket;
impl<'a> Parse<'a> for StopPacket {
fn parse(_stream: &mut Stream, _state: &ParserState) -> Result<Self> {
impl BitRead<LittleEndian> for StopPacket {
fn read(_stream: &mut Stream) -> ReadResult<Self> {
Ok(StopPacket)
}
fn skip(_stream: &mut Stream) -> Result<()> {
Ok(())
}
}

View file

@ -1,31 +1,33 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use bitstream_reader::{BitRead, LittleEndian};
use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
use std::fmt;
#[derive(Debug)]
pub struct StringTable<'a> {
pub struct StringTable {
name: String,
entries: Vec<StringTableEntry<'a>>,
entries: Vec<StringTableEntry>,
max_entries: u32,
fixed_userdata_size: Option<u32>,
fixed_userdata_size_bits: Option<u32>,
client_entries: Option<Vec<StringTableEntry<'a>>>,
client_entries: Option<Vec<StringTableEntry>>,
compressed: bool,
}
impl<'a> StringTable<'a> {
fn parse(stream: &mut Stream<'a>) -> Result<Self> {
impl BitRead<LittleEndian> for StringTable {
fn read(stream: &mut Stream) -> ReadResult <Self> {
let name = stream.read_string(None)?;
let entry_count: u32 = stream.read(16)?;
let entry_count: u32 = stream.read_int(16)?;
let mut entries = Vec::with_capacity(entry_count as usize);
for _ in 0..entry_count {
entries.push(StringTableEntry::parse(stream)?);
entries.push(StringTableEntry::read(stream)?);
}
let client_entries = if stream.read_bool()? {
let count = stream.read(16)?;
let count = stream.read_int(16)?;
let mut vec = Vec::with_capacity(count);
for _ in 0..count {
vec.push(StringTableEntry::parse(stream)?);
vec.push(StringTableEntry::read(stream)?);
}
Some(vec)
} else {
@ -44,16 +46,16 @@ impl<'a> StringTable<'a> {
}
}
pub struct StringTableEntry<'a> {
pub struct StringTableEntry {
text: String,
extra_data: Option<Stream<'a>>,
extra_data: Option<Stream>,
}
impl<'a> StringTableEntry<'a> {
fn parse(stream: &mut Stream<'a>) -> Result<Self> {
impl BitRead<LittleEndian> for StringTableEntry {
fn read(stream: &mut Stream) -> ReadResult<Self> {
let text = stream.read_string(None)?;
let extra_data = if stream.read_bool()? {
let byte_len: usize = stream.read(16)?;
let byte_len: usize = stream.read_int(16)?;
Some(stream.read_bits(byte_len * 8)?)
} else {
None
@ -62,31 +64,36 @@ impl<'a> StringTableEntry<'a> {
}
}
impl<'a> fmt::Debug for StringTableEntry<'a> {
impl fmt::Debug for StringTableEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.extra_data {
None => write!(f, "Table Entry: '{}'", self.text),
Some(extra_data) => write!(f, "Table Entry: '{}' with {} bits of extra data", self.text, extra_data.bit_len())
Some(extra_data) => write!(
f,
"Table Entry: '{}' with {} bits of extra data",
self.text,
extra_data.bit_len()
),
}
}
}
#[derive(Debug)]
pub struct StringTablePacket<'a> {
pub struct StringTablePacket {
tick: u32,
tables: Vec<StringTable<'a>>,
tables: Vec<StringTable>,
}
impl<'a> Parse<'a> for StringTablePacket<'a> {
fn parse(stream: &mut Stream<'a>, _state: &ParserState<'a>) -> Result<Self> {
let tick = stream.read(32)?;
impl Parse for StringTablePacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let tick = stream.read_int(32)?;
let start = stream.pos();
let length: usize = stream.read(32)?;
let length: usize = stream.read_int(32)?;
let mut packet_data = stream.read_bits(length * 8)?;
let count: u32 = packet_data.read(8)?;
let count: u32 = packet_data.read_int(8)?;
let mut tables = Vec::with_capacity(count as usize);
for _ in 0..count {
tables.push(StringTable::parse(&mut packet_data)?);
tables.push(StringTable::read(&mut packet_data)?);
}
if packet_data.bits_left() > 7 {
Err(ParseError::DataRemaining(packet_data.bits_left()))
@ -94,10 +101,4 @@ impl<'a> Parse<'a> for StringTablePacket<'a> {
Ok(StringTablePacket { tick, tables })
}
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32)?;
let length = stream.read::<usize>(32)?;
stream.skip(length).map_err(ParseError::from)
}
}

View file

@ -1,18 +1,8 @@
use bitstream_reader::{BitRead};
use crate::{Parse, ParseError, ParserState, Result, Stream};
#[derive(Debug)]
#[derive(BitRead, Debug)]
pub struct SyncTickPacket {
tick: u32,
}
impl<'a> Parse<'a> for SyncTickPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(SyncTickPacket {
tick: stream.read(32)?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(32).map_err(ParseError::from)
}
}
}

View file

@ -1,4 +1,6 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use bitstream_reader::{BitRead, LittleEndian};
use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
#[derive(Debug)]
pub struct UserCmdPacket {
@ -6,22 +8,13 @@ pub struct UserCmdPacket {
sequence_out: u32,
}
impl<'a> Parse<'a> for UserCmdPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let tick = stream.read(32)?;
let sequence_out = stream.read(32)?;
let len = stream.read::<usize>(32)?;
impl BitRead<LittleEndian> for UserCmdPacket {
fn read(stream: &mut Stream) -> ReadResult<Self> {
let tick = stream.read_int(32)?;
let sequence_out = stream.read_int(32)?;
let len = stream.read_int::<usize>(32)?;
let mut _packet_data = stream.read_bits(len * 8)?;
// TODO parse the packet data
Ok(UserCmdPacket {
tick,
sequence_out
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(64)?;
let len = stream.read::<usize>(32)?;
stream.skip(len * 8).map_err(ParseError::from)
Ok(UserCmdPacket { tick, sequence_out })
}
}

View file

@ -1,6 +1,6 @@
use std::error::Error;
use bitstream_reader::ReadError;
use bitstream_reader::{ReadError, BitRead, LittleEndian};
use crate::demo::header::Header;
use crate::demo::packet::Packet;
@ -16,6 +16,8 @@ pub enum ParseError {
ReadError(ReadError),
/// Packet identifier is invalid
InvalidPacketType(u8),
/// Message identifier is invalid
InvalidMessageType(u8),
/// SendProp type is invalid
InvalidSendPropType(u8),
/// Invalid structure found while creating array SendProp
@ -32,29 +34,43 @@ impl From<ReadError> for ParseError {
pub type Result<T> = std::result::Result<T, ParseError>;
pub trait Parse<'a>: Sized {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self>;
fn skip(stream: &mut Stream) -> Result<()>;
pub trait Parse: Sized {
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self>;
fn skip(stream: &mut Stream) -> Result<()> {
let _ = Self::parse(stream, &ParserState::new())?;
Ok(())
}
}
pub struct DemoParser<'a> {
stream: Stream<'a>,
state: ParserState<'a>,
impl<T: BitRead<LittleEndian>> Parse for T {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Self::read(stream).map_err(ParseError::from)
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = Self::parse(stream, &ParserState::new())?;
Ok(())
}
}
impl<'a> DemoParser<'a> {
pub fn new(stream: Stream<'a>) -> Self {
pub struct DemoParser {
stream: Stream,
state: ParserState,
}
impl DemoParser {
pub fn new(stream: Stream) -> Self {
DemoParser {
state: ParserState::new(&stream),
state: ParserState::new(),
stream,
}
}
pub fn read<T: Parse<'a>>(&mut self) -> Result<T> {
pub fn read<T: Parse>(&mut self) -> Result<T> {
T::parse(&mut self.stream, &self.state)
}
pub fn skip<T: Parse<'a>>(&mut self) -> Result<()> {
pub fn skip<T: Parse>(&mut self) -> Result<()> {
T::skip(&mut self.stream)
}
@ -67,7 +83,7 @@ impl<'a> DemoParser<'a> {
Ok(())
}
pub fn split_packets(mut self) -> Result<Vec<Stream<'a>>> {
pub fn split_packets(mut self) -> Result<Vec<Stream>> {
let _ = self.skip::<Header>()?;
let mut streams = vec![];
while self.stream.bits_left() > 7 {
@ -80,14 +96,14 @@ impl<'a> DemoParser<'a> {
Ok(streams)
}
pub fn parse_demo(mut self) -> Result<(Header, Vec<Packet<'a>>)> {
pub fn parse_demo(mut self) -> Result<(Header, Vec<Packet>)> {
let header = self.read::<Header>()?;
let mut packets = vec![];
loop {
let packet = self.read::<Packet>()?;
match packet {
Packet::Stop(_) => break,
packet => packets.push(packet)
packet => packets.push(packet),
}
}
Ok((header, packets))

View file

@ -3,20 +3,20 @@ use crate::demo::sendprop::SendProp;
use crate::Stream;
use std::collections::HashMap;
pub struct ParserState<'a> {
pub struct ParserState {
pub version: u32,
pub static_baselines: HashMap<u32, StaticBaseline<'a>>,
pub static_baselines: HashMap<u32, StaticBaseline>,
pub event_definitions: HashMap<u32, GameEventDefinition>,
}
pub struct StaticBaseline<'a> {
pub struct StaticBaseline {
class_id: u32,
raw: Stream<'a>,
raw: Stream,
parsed: Option<Vec<SendProp>>,
}
impl<'a> ParserState<'a> {
pub fn new(_stream: &Stream<'a>) -> Self {
impl ParserState {
pub fn new() -> Self {
ParserState {
version: 0,
static_baselines: HashMap::new(),

View file

@ -1,9 +1,10 @@
use bitstream_reader::{BitRead, LittleEndian};
use enum_primitive_derive::Primitive;
use enumflags2::BitFlags;
use enumflags2_derive::EnumFlags;
use num_traits::cast::FromPrimitive;
use crate::{Parse, ParseError, ParserState, Result, Stream};
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use super::packet::datatable::SendTable;
use super::vector::{Vector, VectorXY};
@ -12,7 +13,7 @@ use super::vector::{Vector, VectorXY};
pub struct SendPropDefinition {
pub prop_type: SendPropType,
pub name: String,
pub flags: BitFlags<SendPropFlag>,
pub flags: SendPropFlags,
pub exclude_dt_name: Option<String>,
pub low_value: Option<f32>,
pub high_value: Option<f32>,
@ -25,10 +26,13 @@ pub struct SendPropDefinition {
}
impl SendPropDefinition {
pub fn parse<'a>(stream: &mut Stream<'a>, state: &ParserState<'a>, owner_table_name: String) -> Result<Self> {
let prop_type = SendPropType::parse(stream, state)?;
pub fn read(
stream: &mut Stream,
owner_table_name: String,
) -> Result<Self> {
let prop_type = SendPropType::read(stream)?;
let name = stream.read_string(None)?;
let flags = BitFlags::<SendPropFlag>::parse(stream, state)?;
let flags = SendPropFlags::read(stream)?;
let mut exclude_dt_name = None;
let mut element_count = None;
let mut low_value = None;
@ -40,11 +44,11 @@ impl SendPropDefinition {
if flags.contains(SendPropFlag::Exclude) {
exclude_dt_name = Some(stream.read_string(None)?);
} else if prop_type == SendPropType::Array {
element_count = Some(stream.read(10)?);
element_count = Some(stream.read_int(10)?);
} else {
low_value = Some(stream.read_float()?);
high_value = Some(stream.read_float()?);
bit_count = Some(stream.read(7)?);
bit_count = Some(stream.read_int(7)?);
}
}
let original_bit_count = bit_count;
@ -52,7 +56,9 @@ impl SendPropDefinition {
if flags.contains(SendPropFlag::NoScale) {
if prop_type == SendPropType::Float {
bit_count = Some(32);
} else if prop_type == SendPropType::Vector && !flags.contains(SendPropFlag::NormalVarInt) {
} else if prop_type == SendPropType::Vector
&& !flags.contains(SendPropFlag::NormalVarInt)
{
bit_count = Some(32 * 3);
}
}
@ -91,7 +97,8 @@ impl SendPropDefinition {
}
}
#[derive(Primitive, Copy, Clone, PartialEq, Debug)]
#[derive(BitRead, Copy, Clone, PartialEq, Debug)]
#[discriminant_bits = 5]
pub enum SendPropType {
Int = 0,
Float = 1,
@ -103,18 +110,6 @@ pub enum SendPropType {
NumSendPropTypes = 7,
}
impl Parse<'_> for SendPropType {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let raw = stream.read(5)?;
let prop_type: Option<SendPropType> = SendPropType::from_u8(raw);
prop_type.ok_or(ParseError::InvalidSendPropType(raw))
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(5).map_err(ParseError::from)
}
}
#[derive(EnumFlags, Copy, Clone, PartialEq, Debug)]
#[repr(u16)]
pub enum SendPropFlag {
@ -177,15 +172,20 @@ pub enum SendPropFlag {
NormalVarInt = 32, //(1 << 5)
}
impl Parse<'_> for BitFlags<SendPropFlag> {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let raw = stream.read(16)?;
// since all 16 bits worth of flags are used there are no invalid flags
Ok(BitFlags::from_bits_truncate(raw))
}
#[derive(Debug, Copy, Clone)]
pub struct SendPropFlags(BitFlags<SendPropFlag>);
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(16).map_err(ParseError::from)
impl SendPropFlags {
pub fn contains(self, other: SendPropFlag) -> bool {
self.0.contains(other)
}
}
impl BitRead<LittleEndian> for SendPropFlags {
fn read(stream: &mut Stream) -> ReadResult<Self> {
let raw = stream.read_int(16)?;
// since all 16 bits worth of flags are used there are no invalid flags
Ok(SendPropFlags(BitFlags::from_bits_truncate(raw)))
}
}

View file

@ -1,41 +1,16 @@
use bitstream_reader::BitRead;
use crate::{Parse, ParseError, ParserState, Result, Stream};
#[derive(Debug)]
#[derive(BitRead, Debug)]
pub struct Vector {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl Parse<'_> for Vector {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(Vector {
x: stream.read_float()?,
y: stream.read_float()?,
z: stream.read_float()?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(32 * 3).map_err(ParseError::from)
}
}
#[derive(Debug)]
#[derive(BitRead, Debug)]
pub struct VectorXY {
pub x: f32,
pub y: f32,
}
impl Parse<'_> for VectorXY {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(VectorXY {
x: stream.read_float()?,
y: stream.read_float()?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(32 * 2).map_err(ParseError::from)
}
}