mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
fix packet parsers
This commit is contained in:
parent
b41bb56822
commit
5f4af8333b
13 changed files with 132 additions and 48 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
use bitstream_reader::{BitBuffer, BitStream, LittleEndian, NonPadded};
|
use bitstream_reader::{BitBuffer, BitStream, LittleEndian, NonPadded};
|
||||||
|
use crate::{ParserState, Parse, ParseError, Result};
|
||||||
use rentals::OwnedBuffer;
|
use rentals::OwnedBuffer;
|
||||||
|
|
||||||
pub mod gamevent;
|
pub mod gamevent;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ConsoleCmdPacket {
|
pub struct ConsoleCmdPacket {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
command: String,
|
command: String,
|
||||||
|
|
@ -8,16 +9,18 @@ pub struct ConsoleCmdPacket {
|
||||||
impl<'a> Parse<'a> for ConsoleCmdPacket {
|
impl<'a> Parse<'a> for ConsoleCmdPacket {
|
||||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||||
let tick = stream.read(32)?;
|
let tick = stream.read(32)?;
|
||||||
let len = stream.read(32)?;
|
let len = stream.read::<usize>(32)?;
|
||||||
|
let mut packet_data = stream.read_bits(len * 8)?;
|
||||||
|
let command = packet_data.read_string(None)?;
|
||||||
Ok(ConsoleCmdPacket {
|
Ok(ConsoleCmdPacket {
|
||||||
tick,
|
tick,
|
||||||
command: stream.read_string(Some(len))?,
|
command,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> Result<()> {
|
fn skip(stream: &mut Stream) -> Result<()> {
|
||||||
let _ = stream.skip(32)?;
|
let _ = stream.skip(32)?;
|
||||||
let len = stream.read(32)?;
|
let len = stream.read::<usize>(32)?;
|
||||||
stream.skip(len).map_err(ParseError::from)
|
stream.skip(len * 8).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropType};
|
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropType};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ServerClass {
|
pub struct ServerClass {
|
||||||
id: u32,
|
id: u32,
|
||||||
name: String,
|
name: String,
|
||||||
data_table: String,
|
data_table: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SendTable {
|
pub struct SendTable {
|
||||||
name: String,
|
name: String,
|
||||||
props: Vec<SendPropDefinition>,
|
props: Vec<SendPropDefinition>,
|
||||||
|
|
@ -14,6 +16,7 @@ pub struct SendTable {
|
||||||
flattened_props: Option<Vec<SendPropDefinition>>,
|
flattened_props: Option<Vec<SendPropDefinition>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct DataTablePacket {
|
pub struct DataTablePacket {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
tables: Vec<SendTable>,
|
tables: Vec<SendTable>,
|
||||||
|
|
@ -23,27 +26,29 @@ pub struct DataTablePacket {
|
||||||
impl<'a> Parse<'a> for DataTablePacket {
|
impl<'a> Parse<'a> for DataTablePacket {
|
||||||
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
|
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
|
||||||
let tick = stream.read(32)?;
|
let tick = stream.read(32)?;
|
||||||
let _len = stream.read::<u32>(32)?;
|
let start = stream.pos();
|
||||||
|
let len = stream.read::<usize>(32)?;
|
||||||
|
let mut packet_data = stream.read_bits(len * 8)?;
|
||||||
|
|
||||||
let mut tables = vec![];
|
let mut tables = vec![];
|
||||||
while stream.read_bool()? {
|
while packet_data.read_bool()? {
|
||||||
let needs_decoder = stream.read_bool()?;
|
let needs_decoder = packet_data.read_bool()?;
|
||||||
let name = stream.read_string(None)?;
|
let name = packet_data.read_string(None)?;
|
||||||
let prop_count = stream.read(10)?;
|
let prop_count = packet_data.read(10)?;
|
||||||
|
|
||||||
let mut array_element_prop = None;
|
let mut array_element_prop = None;
|
||||||
let mut props = Vec::with_capacity(prop_count);
|
let mut props = Vec::with_capacity(prop_count);
|
||||||
|
|
||||||
for i in 0..prop_count {
|
for i in 0..prop_count {
|
||||||
let prop: SendPropDefinition = SendPropDefinition::parse(stream, state, name.clone())?;
|
let prop: SendPropDefinition = SendPropDefinition::parse(&mut packet_data, state, name.clone())?;
|
||||||
if prop.flags.contains(SendPropFlag::InsideArray) {
|
if prop.flags.contains(SendPropFlag::InsideArray) {
|
||||||
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
|
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
|
||||||
return Err(ParseError::InvalidSendPropArray);
|
return Err(ParseError::InvalidSendPropArray("Array contents can't have the 'ChangesOften' flag".to_owned()));
|
||||||
}
|
}
|
||||||
array_element_prop = Some(prop);
|
array_element_prop = Some(prop);
|
||||||
} else if let Some(array_element) = array_element_prop {
|
} else if let Some(array_element) = array_element_prop {
|
||||||
if prop.prop_type == SendPropType::Array {
|
if prop.prop_type != SendPropType::Array {
|
||||||
return Err(ParseError::InvalidSendPropArray);
|
return Err(ParseError::InvalidSendPropArray("Array contents can without array".to_owned()));
|
||||||
}
|
}
|
||||||
array_element_prop = None;
|
array_element_prop = None;
|
||||||
props.push(prop.with_array_property(array_element));
|
props.push(prop.with_array_property(array_element));
|
||||||
|
|
@ -63,12 +68,12 @@ impl<'a> Parse<'a> for DataTablePacket {
|
||||||
|
|
||||||
// TODO linked tables?
|
// TODO linked tables?
|
||||||
|
|
||||||
let server_class_count = stream.read(16)?;
|
let server_class_count = packet_data.read(16)?;
|
||||||
let mut server_classes = Vec::with_capacity(server_class_count);
|
let mut server_classes = Vec::with_capacity(server_class_count);
|
||||||
for i in 0..server_class_count {
|
for i in 0..server_class_count {
|
||||||
let id = stream.read(16)?;
|
let id = packet_data.read(16)?;
|
||||||
let name = stream.read_string(None)?;
|
let name = packet_data.read_string(None)?;
|
||||||
let data_table = stream.read_string(None)?;
|
let data_table = packet_data.read_string(None)?;
|
||||||
server_classes.push(ServerClass {
|
server_classes.push(ServerClass {
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
|
|
@ -76,16 +81,20 @@ impl<'a> Parse<'a> for DataTablePacket {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if packet_data.bits_left() > 7 {
|
||||||
|
Err(ParseError::DataRemaining(packet_data.bits_left()))
|
||||||
|
} else {
|
||||||
Ok(DataTablePacket {
|
Ok(DataTablePacket {
|
||||||
tick,
|
tick,
|
||||||
tables,
|
tables,
|
||||||
server_classes,
|
server_classes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> Result<()> {
|
fn skip(stream: &mut Stream) -> Result<()> {
|
||||||
let _ = stream.skip(32)?;
|
let _ = stream.skip(32)?;
|
||||||
let len = stream.read(32)?;
|
let len = stream.read::<usize>(32)?;
|
||||||
stream.skip(len).map_err(ParseError::from)
|
stream.skip(len * 8).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Message;
|
pub struct Message;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct MessagePacket {
|
pub struct MessagePacket {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
messages: Vec<Message>,
|
messages: Vec<Message>,
|
||||||
|
|
@ -29,11 +31,11 @@ impl<'a> Parse<'a> for MessagePacket {
|
||||||
let sequence_in = stream.read(32)?;
|
let sequence_in = stream.read(32)?;
|
||||||
let sequence_out = stream.read(32)?;
|
let sequence_out = stream.read(32)?;
|
||||||
let length: usize = stream.read(32)?;
|
let length: usize = stream.read(32)?;
|
||||||
let _ = stream.skip(length).map_err(ParseError::from);
|
let mut packet_data = stream.read_bits(length * 8)?;
|
||||||
|
|
||||||
let mut messages = vec![];
|
let messages = vec![];
|
||||||
|
|
||||||
Ok(MessagePacket {
|
let packet = MessagePacket {
|
||||||
tick,
|
tick,
|
||||||
messages,
|
messages,
|
||||||
view_origin,
|
view_origin,
|
||||||
|
|
@ -42,7 +44,8 @@ impl<'a> Parse<'a> for MessagePacket {
|
||||||
sequence_in,
|
sequence_in,
|
||||||
sequence_out,
|
sequence_out,
|
||||||
flags,
|
flags,
|
||||||
})
|
};
|
||||||
|
Ok(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> Result<()> {
|
fn skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
|
@ -53,7 +56,7 @@ impl<'a> Parse<'a> for MessagePacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = stream.skip(32 * 2)?;
|
let _ = stream.skip(32 * 2)?;
|
||||||
let length: usize = stream.read(32)?;
|
let length: usize = stream.read::<usize>(32)?;
|
||||||
stream.skip(length).map_err(ParseError::from)
|
stream.skip(length * 8).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,7 @@ pub mod usercmd;
|
||||||
pub mod datatable;
|
pub mod datatable;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Packet<'a> {
|
pub enum Packet<'a> {
|
||||||
Sigon(MessagePacket),
|
Sigon(MessagePacket),
|
||||||
Message(MessagePacket),
|
Message(MessagePacket),
|
||||||
|
|
@ -30,7 +31,7 @@ pub enum Packet<'a> {
|
||||||
StringTables(StringTablePacket<'a>),
|
StringTables(StringTablePacket<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Primitive)]
|
#[derive(Primitive, Debug)]
|
||||||
pub enum PacketType {
|
pub enum PacketType {
|
||||||
Sigon = 1,
|
Sigon = 1,
|
||||||
Message = 2,
|
Message = 2,
|
||||||
|
|
@ -71,6 +72,7 @@ impl<'a> Parse<'a> for Packet<'a> {
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> Result<()> {
|
fn skip(stream: &mut Stream) -> Result<()> {
|
||||||
let packet_type = PacketType::parse(stream, &ParserState::new(&stream))?;
|
let packet_type = PacketType::parse(stream, &ParserState::new(&stream))?;
|
||||||
|
dbg!(&packet_type);
|
||||||
match packet_type {
|
match packet_type {
|
||||||
PacketType::Sigon => MessagePacket::skip(stream),
|
PacketType::Sigon => MessagePacket::skip(stream),
|
||||||
PacketType::Message => MessagePacket::skip(stream),
|
PacketType::Message => MessagePacket::skip(stream),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{Parse, ParserState, Result, Stream};
|
use crate::{Parse, ParserState, Result, Stream};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct StopPacket;
|
pub struct StopPacket;
|
||||||
|
|
||||||
impl<'a> Parse<'a> for StopPacket {
|
impl<'a> Parse<'a> for StopPacket {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct StringTable<'a> {
|
pub struct StringTable<'a> {
|
||||||
name: String,
|
name: String,
|
||||||
entries: Vec<StringTableEntry<'a>>,
|
entries: Vec<StringTableEntry<'a>>,
|
||||||
|
|
@ -60,6 +62,16 @@ impl<'a> StringTableEntry<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Debug for StringTableEntry<'a> {
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct StringTablePacket<'a> {
|
pub struct StringTablePacket<'a> {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
tables: Vec<StringTable<'a>>,
|
tables: Vec<StringTable<'a>>,
|
||||||
|
|
@ -68,18 +80,24 @@ pub struct StringTablePacket<'a> {
|
||||||
impl<'a> Parse<'a> for StringTablePacket<'a> {
|
impl<'a> Parse<'a> for StringTablePacket<'a> {
|
||||||
fn parse(stream: &mut Stream<'a>, _state: &ParserState<'a>) -> Result<Self> {
|
fn parse(stream: &mut Stream<'a>, _state: &ParserState<'a>) -> Result<Self> {
|
||||||
let tick = stream.read(32)?;
|
let tick = stream.read(32)?;
|
||||||
|
let start = stream.pos();
|
||||||
let length: usize = stream.read(32)?;
|
let length: usize = stream.read(32)?;
|
||||||
let count: u32 = stream.read(8)?;
|
let mut packet_data = stream.read_bits(length * 8)?;
|
||||||
|
let count: u32 = packet_data.read(8)?;
|
||||||
let mut tables = Vec::with_capacity(count as usize);
|
let mut tables = Vec::with_capacity(count as usize);
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
tables.push(StringTable::parse(stream)?);
|
tables.push(StringTable::parse(&mut packet_data)?);
|
||||||
}
|
}
|
||||||
|
if packet_data.bits_left() > 7 {
|
||||||
|
Err(ParseError::DataRemaining(packet_data.bits_left()))
|
||||||
|
} else {
|
||||||
Ok(StringTablePacket { tick, tables })
|
Ok(StringTablePacket { tick, tables })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> Result<()> {
|
fn skip(stream: &mut Stream) -> Result<()> {
|
||||||
let _ = stream.skip(32)?;
|
let _ = stream.skip(32)?;
|
||||||
let length = stream.read(32)?;
|
let length = stream.read::<usize>(32)?;
|
||||||
stream.skip(length).map_err(ParseError::from)
|
stream.skip(length).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SyncTickPacket {
|
pub struct SyncTickPacket {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct UserCmdPacket {
|
pub struct UserCmdPacket {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
command: String,
|
|
||||||
sequence_out: u32,
|
sequence_out: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -10,17 +10,18 @@ impl<'a> Parse<'a> for UserCmdPacket {
|
||||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||||
let tick = stream.read(32)?;
|
let tick = stream.read(32)?;
|
||||||
let sequence_out = stream.read(32)?;
|
let sequence_out = stream.read(32)?;
|
||||||
let len = stream.read(32)?;
|
let len = stream.read::<usize>(32)?;
|
||||||
|
let mut _packet_data = stream.read_bits(len * 8)?;
|
||||||
|
// TODO parse the packet data
|
||||||
Ok(UserCmdPacket {
|
Ok(UserCmdPacket {
|
||||||
tick,
|
tick,
|
||||||
sequence_out,
|
sequence_out
|
||||||
command: stream.read_string(Some(len))?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip(stream: &mut Stream) -> Result<()> {
|
fn skip(stream: &mut Stream) -> Result<()> {
|
||||||
let _ = stream.skip(64)?;
|
let _ = stream.skip(64)?;
|
||||||
let len = stream.read(32)?;
|
let len = stream.read::<usize>(32)?;
|
||||||
stream.skip(len).map_err(ParseError::from)
|
stream.skip(len * 8).map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use bitstream_reader::ReadError;
|
||||||
|
|
||||||
|
use crate::demo::header::Header;
|
||||||
|
use crate::demo::packet::Packet;
|
||||||
pub use crate::demo::parser::state::ParserState;
|
pub use crate::demo::parser::state::ParserState;
|
||||||
use crate::Stream;
|
use crate::Stream;
|
||||||
use bitstream_reader::ReadError;
|
|
||||||
|
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
|
|
@ -14,7 +19,9 @@ pub enum ParseError {
|
||||||
/// SendProp type is invalid
|
/// SendProp type is invalid
|
||||||
InvalidSendPropType(u8),
|
InvalidSendPropType(u8),
|
||||||
/// Invalid structure found while creating array SendProp
|
/// Invalid structure found while creating array SendProp
|
||||||
InvalidSendPropArray,
|
InvalidSendPropArray(String),
|
||||||
|
/// Expected amount of data left after parsing an object
|
||||||
|
DataRemaining(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ReadError> for ParseError {
|
impl From<ReadError> for ParseError {
|
||||||
|
|
@ -59,4 +66,30 @@ impl<'a> DemoParser<'a> {
|
||||||
self.stream.set_pos(pos)?;
|
self.stream.set_pos(pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split_packets(mut self) -> Result<Vec<Stream<'a>>> {
|
||||||
|
let _ = self.skip::<Header>()?;
|
||||||
|
let mut streams = vec![];
|
||||||
|
while self.stream.bits_left() > 7 {
|
||||||
|
let start = self.stream.pos();
|
||||||
|
let _ = self.skip::<Packet>()?;
|
||||||
|
let end = self.stream.pos();
|
||||||
|
let _ = self.stream.set_pos(start);
|
||||||
|
streams.push(self.stream.read_bits(end - start)?);
|
||||||
|
}
|
||||||
|
Ok(streams)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_demo(mut self) -> Result<(Header, Vec<Packet<'a>>)> {
|
||||||
|
let header = self.read::<Header>()?;
|
||||||
|
let mut packets = vec![];
|
||||||
|
loop {
|
||||||
|
let packet = self.read::<Packet>()?;
|
||||||
|
match packet {
|
||||||
|
Packet::Stop(_) => break,
|
||||||
|
packet => packets.push(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((header, packets))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
use super::packet::datatable::SendTable;
|
use super::packet::datatable::SendTable;
|
||||||
use super::vector::{Vector, VectorXY};
|
use super::vector::{Vector, VectorXY};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SendPropDefinition {
|
pub struct SendPropDefinition {
|
||||||
pub prop_type: SendPropType,
|
pub prop_type: SendPropType,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Vector {
|
pub struct Vector {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
|
|
@ -20,6 +21,7 @@ impl Parse<'_> for Vector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct VectorXY {
|
pub struct VectorXY {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
|
|
|
||||||
17
src/main.rs
17
src/main.rs
|
|
@ -1,15 +1,24 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rental;
|
extern crate rental;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
pub use demo::{
|
pub use demo::{
|
||||||
parser::{DemoParser, Parse, ParseError, ParserState, Result},
|
Demo,
|
||||||
Demo, Stream,
|
parser::{DemoParser, Parse, ParseError, ParserState, Result}, Stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod demo;
|
mod demo;
|
||||||
mod state;
|
mod state;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
fn main() {
|
fn main() -> std::result::Result<(), Box<ParseError>> {
|
||||||
println!("Hello, world!");
|
let file = fs::read("data/small.dem").expect("Unable to read file");
|
||||||
|
let demo = Demo::new(file);
|
||||||
|
let stream: Stream = demo.get_stream();
|
||||||
|
let mut parser = DemoParser::new(stream);
|
||||||
|
let (header, packets) = parser.parse_demo()?;
|
||||||
|
dbg!(header);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue