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

remove the need to read raw game event before transforming into game event

This commit is contained in:
Robin Appelman 2021-07-16 23:51:35 +02:00
commit 36077864ad
6 changed files with 6032 additions and 5027 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
use bitbuffer::{BitRead, BitWrite};
use crate::{ParseError, Result};
use crate::{GameEventError, ParseError, Result, Stream};
pub use super::gameevent_gen::{GameEvent, GameEventType};
use crate::demo::handle_utf8_error;
use crate::demo::message::gameevent::GameEventTypeId;
use parse_display::Display;
use std::cmp::Ordering;
@ -65,6 +66,21 @@ pub enum GameEventValue {
Local,
}
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
Ok(match definition.kind {
GameEventValueType::String => {
GameEventValue::String(stream.read().or_else(handle_utf8_error)?)
}
GameEventValueType::Float => GameEventValue::Float(stream.read()?),
GameEventValueType::Long => GameEventValue::Long(stream.read()?),
GameEventValueType::Short => GameEventValue::Short(stream.read()?),
GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
GameEventValueType::Local => GameEventValue::Local,
GameEventValueType::None => return Err(GameEventError::NoneValue.into()),
})
}
impl GameEventValue {
pub fn get_type(&self) -> GameEventValueType {
match self {
@ -81,6 +97,8 @@ impl GameEventValue {
pub trait FromGameEventValue: Sized {
fn from_value(value: Option<GameEventValue>, name: &'static str) -> Result<Self>;
fn value_type() -> GameEventValueType;
}
impl FromGameEventValue for String {
@ -95,6 +113,10 @@ impl FromGameEventValue for String {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::String
}
}
impl FromGameEventValue for f32 {
@ -109,6 +131,10 @@ impl FromGameEventValue for f32 {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::Float
}
}
impl FromGameEventValue for u32 {
@ -125,6 +151,10 @@ impl FromGameEventValue for u32 {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::Long
}
}
impl FromGameEventValue for u16 {
@ -141,6 +171,10 @@ impl FromGameEventValue for u16 {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::Short
}
}
impl FromGameEventValue for u8 {
@ -157,6 +191,10 @@ impl FromGameEventValue for u8 {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::Byte
}
}
impl FromGameEventValue for bool {
@ -171,6 +209,10 @@ impl FromGameEventValue for bool {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::Boolean
}
}
impl FromGameEventValue for () {
@ -184,6 +226,10 @@ impl FromGameEventValue for () {
}),
}
}
fn value_type() -> GameEventValueType {
GameEventValueType::Local
}
}
#[derive(Debug)]
@ -192,6 +238,20 @@ pub struct RawGameEvent {
pub values: Vec<GameEventValue>,
}
impl RawGameEvent {
pub fn read(stream: &mut Stream, definition: &GameEventDefinition) -> Result<Self> {
let mut values: Vec<GameEventValue> = Vec::with_capacity(definition.entries.len());
for entry in &definition.entries {
values.push(read_event_value(stream, &entry)?);
}
Ok(RawGameEvent {
event_type: definition.event_type,
values,
})
}
}
pub trait FromRawGameEvent: Sized {
fn from_raw_event(values: Vec<GameEventValue>) -> Result<Self>;
}

View file

@ -1,30 +1,13 @@
use bitbuffer::{BitRead, LittleEndian};
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
use parse_display::Display;
use crate::demo::gameevent_gen::GameEventType;
use crate::demo::gamevent::{
GameEvent, GameEventDefinition, GameEventEntry, GameEventValue, GameEventValueType,
RawGameEvent,
GameEvent, GameEventDefinition, GameEventEntry, GameEventValueType, RawGameEvent,
};
use crate::demo::handle_utf8_error;
use crate::demo::parser::ParseBitSkip;
use crate::demo::parser::{Encode, ParseBitSkip};
use crate::{GameEventError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
Ok(match definition.kind {
GameEventValueType::String => {
GameEventValue::String(stream.read().or_else(handle_utf8_error)?)
}
GameEventValueType::Float => GameEventValue::Float(stream.read()?),
GameEventValueType::Long => GameEventValue::Long(stream.read()?),
GameEventValueType::Short => GameEventValue::Short(stream.read()?),
GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
GameEventValueType::Local => GameEventValue::Local,
GameEventValueType::None => return Err(GameEventError::NoneValue.into()),
})
}
#[derive(Debug)]
pub struct GameEventMessage {
pub event: Box<GameEvent>,
@ -46,31 +29,30 @@ impl Parse<'_> for GameEventMessage {
});
}
let raw_event = match state.event_definitions.get(usize::from(event_type)) {
Some(definition) => {
let mut values: Vec<GameEventValue> = Vec::with_capacity(definition.entries.len());
for entry in &definition.entries {
values.push(read_event_value(&mut data, &entry)?);
}
RawGameEvent {
event_type: definition.event_type,
values,
}
}
let event = match state.event_definitions.get(usize::from(event_type)) {
Some(definition) => GameEvent::read(&mut data, definition)?,
None => {
return Err(ParseError::MalformedGameEvent(GameEventError::UnknownType(
event_type,
)));
}
};
let event = GameEvent::from_raw_event(raw_event)?;
Ok(GameEventMessage {
event: Box::new(event),
})
}
}
impl Encode for GameEventMessage {
fn encode(
&self,
stream: &mut BitWriteStream<LittleEndian>,
_state: &ParserState,
) -> Result<()> {
Ok(stream.reserve_length(11, |_stream| Ok(()))?)
}
}
impl ParseBitSkip<'_> for GameEventMessage {
fn parse_skip(stream: &mut Stream) -> Result<()> {
let length: u16 = stream.read_sized(11)?;
@ -78,7 +60,7 @@ impl ParseBitSkip<'_> for GameEventMessage {
}
}
#[derive(BitRead, Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Display)]
#[derive(BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Display)]
pub struct GameEventTypeId(#[size = 9] u16);
impl From<GameEventTypeId> for usize {
@ -123,6 +105,22 @@ impl BitRead<'_, LittleEndian> for GameEventDefinition {
}
}
impl BitWrite<LittleEndian> for GameEventDefinition {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
self.id.write(stream)?;
self.event_type.as_str().write(stream)?;
self.name.write(stream)?;
for entry in self.entries.iter() {
entry.kind.write(stream)?;
entry.name.write(stream)?;
}
GameEventValueType::None.write(stream)?;
Ok(())
}
}
impl BitRead<'_, LittleEndian> for GameEventListMessage {
fn read(stream: &mut Stream) -> ReadResult<Self> {
let count: u16 = stream.read_sized(9)?;
@ -133,3 +131,17 @@ impl BitRead<'_, LittleEndian> for GameEventListMessage {
Ok(GameEventListMessage { event_list })
}
}
impl BitWrite<LittleEndian> for GameEventListMessage {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
(self.event_list.len() as u16).write(stream)?;
stream.reserve_length(20, |stream| {
for event in self.event_list.iter() {
event.write(stream)?;
}
Ok(())
})?;
Ok(())
}
}

View file

@ -1,4 +1,4 @@
use bitbuffer::{BitError, BitRead, LittleEndian};
use bitbuffer::{BitError, BitRead, BitWrite, BitWriteStream, LittleEndian};
pub use self::messagetypeanalyser::MessageTypeAnalyser;
@ -30,6 +30,19 @@ impl<'a, T: BitRead<'a, LittleEndian>> Parse<'a> for T {
Self::read(stream).map_err(ParseError::from)
}
}
pub trait Encode: Sized {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()>;
}
impl<T: BitWrite<LittleEndian>> Encode for T {
fn encode(
&self,
stream: &mut BitWriteStream<LittleEndian>,
_state: &ParserState,
) -> Result<()> {
self.write(stream).map_err(ParseError::from)
}
}
pub trait ParseBitSkip<'a> {
fn parse_skip(stream: &mut Stream<'a>) -> Result<()>;