mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
some error refactoring
This commit is contained in:
parent
6b0442741e
commit
77180520ef
12 changed files with 1671 additions and 1298 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
|
@ -178,6 +178,18 @@ dependencies = [
|
||||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "err-derive"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
|
|
@ -423,6 +435,17 @@ dependencies = [
|
||||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termios"
|
name = "termios"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
|
@ -440,6 +463,7 @@ dependencies = [
|
||||||
"enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"enumflags2 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"enumflags2 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"enumflags2_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"enumflags2_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
@ -513,6 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd"
|
"checksum enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd"
|
||||||
"checksum enumflags2 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8c30a444d141611c4826a1a2e7eba9a494458edf14754945fa37c9c20f6f7563"
|
"checksum enumflags2 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8c30a444d141611c4826a1a2e7eba9a494458edf14754945fa37c9c20f6f7563"
|
||||||
"checksum enumflags2_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e015b3dfedc096cb55cdc5d022d6b4e6b94547212fb94ad2d9ece20bcd88fe3"
|
"checksum enumflags2_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e015b3dfedc096cb55cdc5d022d6b4e6b94547212fb94ad2d9ece20bcd88fe3"
|
||||||
|
"checksum err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3d8ff65eb6c2fc68e76557239d16f5698fd56603925b89856d3f0f7105fd4543"
|
||||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||||
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
||||||
|
|
@ -545,6 +570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||||
|
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
|
||||||
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
|
||||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||||
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ serde = { version = "1.0", features = ["derive", "rc"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
better-panic = "0.1"
|
better-panic = "0.1"
|
||||||
|
err-derive = "0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6"
|
pretty_assertions = "0.6"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,10 @@
|
||||||
use bitstream_reader::BitRead;
|
use bitstream_reader::BitRead;
|
||||||
|
|
||||||
use crate::{ParseError, Result};
|
use crate::{MalformedDemoError, ParseError, Result};
|
||||||
|
|
||||||
pub use super::gameevent_gen::{GameEvent, GameEventType};
|
pub use super::gameevent_gen::{GameEvent, GameEventType};
|
||||||
use crate::demo::message::gameevent::GameEventTypeId;
|
use crate::demo::message::gameevent::GameEventTypeId;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GameEventDefinition {
|
pub struct GameEventDefinition {
|
||||||
|
|
@ -32,6 +33,21 @@ pub enum GameEventValueType {
|
||||||
Local = 7,
|
Local = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for GameEventValueType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
GameEventValueType::None => write!(f, "None"),
|
||||||
|
GameEventValueType::String => write!(f, "String"),
|
||||||
|
GameEventValueType::Float => write!(f, "Float"),
|
||||||
|
GameEventValueType::Long => write!(f, "Long"),
|
||||||
|
GameEventValueType::Short => write!(f, "Short"),
|
||||||
|
GameEventValueType::Byte => write!(f, "Byte"),
|
||||||
|
GameEventValueType::Boolean => write!(f, "Boolean"),
|
||||||
|
GameEventValueType::Local => write!(f, "Local"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum GameEventValue {
|
pub enum GameEventValue {
|
||||||
String(String),
|
String(String),
|
||||||
|
|
@ -43,6 +59,20 @@ pub enum GameEventValue {
|
||||||
Local,
|
Local,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GameEventValue {
|
||||||
|
pub fn get_type(&self) -> GameEventValueType {
|
||||||
|
match self {
|
||||||
|
GameEventValue::String(_) => GameEventValueType::String,
|
||||||
|
GameEventValue::Float(_) => GameEventValueType::Float,
|
||||||
|
GameEventValue::Long(_) => GameEventValueType::Long,
|
||||||
|
GameEventValue::Short(_) => GameEventValueType::Short,
|
||||||
|
GameEventValue::Byte(_) => GameEventValueType::Byte,
|
||||||
|
GameEventValue::Boolean(_) => GameEventValueType::Boolean,
|
||||||
|
GameEventValue::Local => GameEventValueType::Local,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait FromGameEventValue: Sized {
|
pub trait FromGameEventValue: Sized {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self>;
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
@ -51,11 +81,12 @@ impl FromGameEventValue for String {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::String(val) => Ok(val),
|
GameEventValue::String(val) => Ok(val),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::String,
|
expected_type: GameEventValueType::String,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -64,11 +95,12 @@ impl FromGameEventValue for f32 {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::Float(val) => Ok(val),
|
GameEventValue::Float(val) => Ok(val),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::Float,
|
expected_type: GameEventValueType::Float,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -77,11 +109,12 @@ impl FromGameEventValue for u32 {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::Long(val) => Ok(val),
|
GameEventValue::Long(val) => Ok(val),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::Long,
|
expected_type: GameEventValueType::Long,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,11 +123,12 @@ impl FromGameEventValue for u16 {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::Short(val) => Ok(val),
|
GameEventValue::Short(val) => Ok(val),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::Short,
|
expected_type: GameEventValueType::Short,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -103,11 +137,12 @@ impl FromGameEventValue for u8 {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::Byte(val) => Ok(val),
|
GameEventValue::Byte(val) => Ok(val),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::Byte,
|
expected_type: GameEventValueType::Byte,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,11 +151,12 @@ impl FromGameEventValue for bool {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::Boolean(val) => Ok(val),
|
GameEventValue::Boolean(val) => Ok(val),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::Boolean,
|
expected_type: GameEventValueType::Boolean,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,11 +165,12 @@ impl FromGameEventValue for () {
|
||||||
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
fn from_value(value: GameEventValue, name: &'static str) -> Result<Self> {
|
||||||
match value {
|
match value {
|
||||||
GameEventValue::Local => Ok(()),
|
GameEventValue::Local => Ok(()),
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(MalformedDemoError::InvalidGameEvent {
|
||||||
expected_type: GameEventValueType::Local,
|
expected_type: GameEventValueType::Local,
|
||||||
name,
|
name,
|
||||||
value,
|
found_type: value.get_type(),
|
||||||
}),
|
}
|
||||||
|
.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ use crate::demo::gamevent::{
|
||||||
RawGameEvent,
|
RawGameEvent,
|
||||||
};
|
};
|
||||||
use crate::demo::parser::ParseBitSkip;
|
use crate::demo::parser::ParseBitSkip;
|
||||||
use crate::{GameEventError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{
|
||||||
|
GameEventError, MalformedDemoError, Parse, ParseError, ParserState, ReadResult, Result, Stream,
|
||||||
|
};
|
||||||
|
|
||||||
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
|
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
|
||||||
Ok(match definition.kind {
|
Ok(match definition.kind {
|
||||||
|
|
@ -20,9 +22,7 @@ fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<
|
||||||
GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
|
GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
|
||||||
GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
|
GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
|
||||||
GameEventValueType::Local => GameEventValue::Local,
|
GameEventValueType::Local => GameEventValue::Local,
|
||||||
GameEventValueType::None => {
|
GameEventValueType::None => return Err(GameEventError::NoneValue.into()),
|
||||||
return Err(ParseError::MalformedGameEvent(GameEventError::NoneValue))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +48,11 @@ impl Parse for GameEventMessage {
|
||||||
values,
|
values,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => return Err(ParseError::MalformedGameEvent(GameEventError::UnknownType)),
|
None => {
|
||||||
|
return Err(
|
||||||
|
MalformedDemoError::MalformedGameEvent(GameEventError::UnknownType).into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let event = GameEvent::from_raw_event(raw_event)?;
|
let event = GameEvent::from_raw_event(raw_event)?;
|
||||||
Ok(GameEventMessage { event })
|
Ok(GameEventMessage { event })
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use crate::demo::message::tempentities::*;
|
||||||
use crate::demo::message::usermessage::*;
|
use crate::demo::message::usermessage::*;
|
||||||
use crate::demo::message::voice::*;
|
use crate::demo::message::voice::*;
|
||||||
use crate::demo::parser::ParseBitSkip;
|
use crate::demo::parser::ParseBitSkip;
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{MalformedDemoError, Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
|
||||||
pub mod bspdecal;
|
pub mod bspdecal;
|
||||||
pub mod classinfo;
|
pub mod classinfo;
|
||||||
|
|
@ -65,7 +65,7 @@ impl Parse for MessageType {
|
||||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||||
let raw = stream.read_int(6)?;
|
let raw = stream.read_int(6)?;
|
||||||
let prop_type: Option<MessageType> = MessageType::from_u8(raw);
|
let prop_type: Option<MessageType> = MessageType::from_u8(raw);
|
||||||
prop_type.ok_or(ParseError::InvalidMessageType(raw))
|
prop_type.ok_or(MalformedDemoError::InvalidMessageType(raw).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ use num_traits::{PrimInt, Unsigned};
|
||||||
use snap::Decoder;
|
use snap::Decoder;
|
||||||
|
|
||||||
use crate::demo::packet::stringtable::{
|
use crate::demo::packet::stringtable::{
|
||||||
ExtraData, FixedUserdataSize, StringTable, StringTableEntry,
|
ExtraData, FixedUserDataSize, StringTable, StringTableEntry,
|
||||||
};
|
};
|
||||||
use crate::demo::parser::ParseBitSkip;
|
use crate::demo::parser::ParseBitSkip;
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{MalformedDemoError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CreateStringTableMessage {
|
pub struct CreateStringTableMessage {
|
||||||
|
|
@ -16,14 +16,14 @@ pub struct CreateStringTableMessage {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StringTableMeta {
|
pub struct StringTableMeta {
|
||||||
pub max_entries: u16,
|
pub max_entries: u16,
|
||||||
pub fixed_userdata_size: Option<FixedUserdataSize>,
|
pub fixed_userdata_size: Option<FixedUserDataSize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&StringTable> for StringTableMeta {
|
impl From<&StringTable> for StringTableMeta {
|
||||||
fn from(table: &StringTable) -> Self {
|
fn from(table: &StringTable) -> Self {
|
||||||
StringTableMeta {
|
StringTableMeta {
|
||||||
max_entries: table.max_entries,
|
max_entries: table.max_entries,
|
||||||
fixed_userdata_size: table.fixed_userdata_size,
|
fixed_userdata_size: table.fixed_user_data_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +80,7 @@ impl Parse for CreateStringTableMessage {
|
||||||
let table = StringTable {
|
let table = StringTable {
|
||||||
entries,
|
entries,
|
||||||
max_entries,
|
max_entries,
|
||||||
fixed_userdata_size,
|
fixed_user_data_size: fixed_userdata_size,
|
||||||
client_entries: None,
|
client_entries: None,
|
||||||
compressed,
|
compressed,
|
||||||
name,
|
name,
|
||||||
|
|
@ -97,7 +97,7 @@ impl ParseBitSkip for CreateStringTableMessage {
|
||||||
let _: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
let _: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
||||||
let length = read_var_int(stream)?;
|
let length = read_var_int(stream)?;
|
||||||
|
|
||||||
let _: Option<FixedUserdataSize> = stream.read()?;
|
let _: Option<FixedUserDataSize> = stream.read()?;
|
||||||
|
|
||||||
let _: bool = stream.read()?;
|
let _: bool = stream.read()?;
|
||||||
|
|
||||||
|
|
@ -122,7 +122,7 @@ impl Parse for UpdateStringTableMessage {
|
||||||
|
|
||||||
let entries = match state.string_tables.get(table_id as usize) {
|
let entries = match state.string_tables.get(table_id as usize) {
|
||||||
Some(table) => parse_string_table_update(&mut data, table, changed),
|
Some(table) => parse_string_table_update(&mut data, table, changed),
|
||||||
None => return Err(ParseError::StringTableNotFound(table_id)),
|
None => return Err(MalformedDemoError::StringTableNotFound(table_id).into()),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
Ok(UpdateStringTableMessage { table_id, entries })
|
Ok(UpdateStringTableMessage { table_id, entries })
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian};
|
||||||
|
|
||||||
|
use crate::demo::parser::MalformedSendPropDefinitionError;
|
||||||
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropName, SendPropType};
|
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropName, SendPropType};
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{MalformedDemoError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
@ -63,16 +64,12 @@ impl Parse for ParseSendTable {
|
||||||
let prop: SendPropDefinition = SendPropDefinition::read(stream, name.clone())?;
|
let prop: SendPropDefinition = SendPropDefinition::read(stream, 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::InvalidSendProp(
|
return Err(MalformedSendPropDefinitionError::ArrayChangesOften.into());
|
||||||
"Array contents can't have the 'ChangesOften' flag",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
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::InvalidSendProp(
|
return Err(MalformedSendPropDefinitionError::UntypedArray.into());
|
||||||
"Array contents can without array",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
array_element_prop = None;
|
array_element_prop = None;
|
||||||
props.push(prop.with_array_property(array_element));
|
props.push(prop.with_array_property(array_element));
|
||||||
|
|
@ -222,7 +219,7 @@ impl Parse for DataTablePacket {
|
||||||
let server_classes = packet_data.read_sized(server_class_count)?;
|
let server_classes = packet_data.read_sized(server_class_count)?;
|
||||||
|
|
||||||
if packet_data.bits_left() > 7 {
|
if packet_data.bits_left() > 7 {
|
||||||
Err(ParseError::DataRemaining(packet_data.bits_left()))
|
Err(MalformedDemoError::DataRemaining(packet_data.bits_left()).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(DataTablePacket {
|
Ok(DataTablePacket {
|
||||||
tick,
|
tick,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ use std::fmt;
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian};
|
||||||
|
|
||||||
use crate::demo::message::stringtable::StringTableMeta;
|
use crate::demo::message::stringtable::StringTableMeta;
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{MalformedDemoError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
|
||||||
#[derive(BitRead, Clone, Copy, Debug)]
|
#[derive(BitRead, Clone, Copy, Debug)]
|
||||||
pub struct FixedUserdataSize {
|
pub struct FixedUserDataSize {
|
||||||
#[size = 12]
|
#[size = 12]
|
||||||
pub size: u16,
|
pub size: u16,
|
||||||
#[size = 4]
|
#[size = 4]
|
||||||
|
|
@ -18,7 +18,7 @@ pub struct StringTable {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub entries: Vec<(u16, StringTableEntry)>,
|
pub entries: Vec<(u16, StringTableEntry)>,
|
||||||
pub max_entries: u16,
|
pub max_entries: u16,
|
||||||
pub fixed_userdata_size: Option<FixedUserdataSize>,
|
pub fixed_user_data_size: Option<FixedUserDataSize>,
|
||||||
pub client_entries: Option<Vec<StringTableEntry>>,
|
pub client_entries: Option<Vec<StringTableEntry>>,
|
||||||
pub compressed: bool,
|
pub compressed: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ pub struct StringTable {
|
||||||
impl StringTable {
|
impl StringTable {
|
||||||
pub fn get_table_meta(&self) -> StringTableMeta {
|
pub fn get_table_meta(&self) -> StringTableMeta {
|
||||||
StringTableMeta {
|
StringTableMeta {
|
||||||
fixed_userdata_size: self.fixed_userdata_size,
|
fixed_userdata_size: self.fixed_user_data_size,
|
||||||
max_entries: self.max_entries,
|
max_entries: self.max_entries,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ impl BitRead<LittleEndian> for StringTable {
|
||||||
name,
|
name,
|
||||||
entries,
|
entries,
|
||||||
max_entries: entry_count,
|
max_entries: entry_count,
|
||||||
fixed_userdata_size: None,
|
fixed_user_data_size: None,
|
||||||
client_entries,
|
client_entries,
|
||||||
compressed: false,
|
compressed: false,
|
||||||
})
|
})
|
||||||
|
|
@ -125,7 +125,7 @@ impl Parse for StringTablePacket {
|
||||||
let tables = packet_data.read_sized(count)?;
|
let tables = packet_data.read_sized(count)?;
|
||||||
|
|
||||||
if packet_data.bits_left() > 7 {
|
if packet_data.bits_left() > 7 {
|
||||||
Err(ParseError::DataRemaining(packet_data.bits_left()))
|
Err(MalformedDemoError::DataRemaining(packet_data.bits_left()).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(StringTablePacket { tick, tables })
|
Ok(StringTablePacket { tick, tables })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitstream_reader::{BitRead, BitSkip, LittleEndian, ReadError};
|
use bitstream_reader::{BitRead, BitSkip, FromUtf8Error, LittleEndian, ReadError};
|
||||||
|
|
||||||
pub use self::messagetypeanalyser::MessageTypeAnalyser;
|
pub use self::messagetypeanalyser::MessageTypeAnalyser;
|
||||||
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
|
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
|
||||||
|
|
@ -9,6 +9,7 @@ pub use crate::demo::parser::analyser::MatchState;
|
||||||
pub use crate::demo::parser::handler::{DemoHandler, MessageHandler};
|
pub use crate::demo::parser::handler::{DemoHandler, MessageHandler};
|
||||||
pub use crate::demo::parser::state::ParserState;
|
pub use crate::demo::parser::state::ParserState;
|
||||||
use crate::Stream;
|
use crate::Stream;
|
||||||
|
use err_derive::Error;
|
||||||
|
|
||||||
mod analyser;
|
mod analyser;
|
||||||
mod handler;
|
mod handler;
|
||||||
|
|
@ -16,57 +17,101 @@ mod messagetypeanalyser;
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
/// Errors that can occur during parsing
|
/// Errors that can occur during parsing
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
/// Error while reading bits from stream
|
#[error(display = "Error while reading bits from stream: {}", _0)]
|
||||||
ReadError(ReadError),
|
ReadError(#[error(cause)] ReadError),
|
||||||
/// Packet identifier is invalid
|
#[error(display = "Malformed utf8 while reading string")]
|
||||||
InvalidPacketType(u8),
|
MalformedUTF8(#[error(cause)] FromUtf8Error),
|
||||||
/// Message identifier is invalid
|
#[error(display = "Malformed demo file: {}", _0)]
|
||||||
InvalidMessageType(u8),
|
MalformedDemo(#[error(cause)] MalformedDemoError),
|
||||||
/// SendProp type is invalid
|
#[error(display = "Unexpected type of compressed data: {}", _0)]
|
||||||
InvalidSendPropType(u8),
|
|
||||||
/// Invalid SendProp
|
|
||||||
InvalidSendProp(&'static str),
|
|
||||||
/// Expected amount of data left after parsing an object
|
|
||||||
DataRemaining(usize),
|
|
||||||
/// String table that was send for update doesn't exist
|
|
||||||
StringTableNotFound(u8),
|
|
||||||
/// A unknown game event type was read
|
|
||||||
UnknownGameEvent(&'static str),
|
|
||||||
/// A malformed game event was read
|
|
||||||
MalformedGameEvent(GameEventError),
|
|
||||||
/// A read game event doesn't contain the expected values
|
|
||||||
InvalidGameEvent {
|
|
||||||
expected_type: GameEventValueType,
|
|
||||||
name: &'static str,
|
|
||||||
value: GameEventValue,
|
|
||||||
},
|
|
||||||
/// Unexpected type of compressed data
|
|
||||||
UnexpectedCompressionType(String),
|
UnexpectedCompressionType(String),
|
||||||
/// Error while decompressing SNAP compressed string table
|
#[error(
|
||||||
SnapError(snap::Error),
|
display = "Error while decompressing SNAP compressed string table: {}",
|
||||||
/// Unexpected size after decompressing SNAP data
|
_0
|
||||||
|
)]
|
||||||
|
SnapError(#[error(cause)] snap::Error),
|
||||||
|
#[error(
|
||||||
|
display = "Unexpected size after decompressing SNAP data, got {} bytes, expected {} bytes",
|
||||||
|
size,
|
||||||
|
expected
|
||||||
|
)]
|
||||||
UnexpectedDecompressedSize {
|
UnexpectedDecompressedSize {
|
||||||
/// Expected decompressed size
|
/// Expected decompressed size
|
||||||
expected: u32,
|
expected: u32,
|
||||||
/// Actual decompressed size
|
/// Actual decompressed size
|
||||||
size: u32,
|
size: u32,
|
||||||
},
|
},
|
||||||
/// Misc malformed demo error
|
#[error(display = "Malformed demo file: {}", _0)]
|
||||||
InvalidDemo(&'static str),
|
InvalidDemo(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
/// Malformed demo file
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum MalformedDemoError {
|
||||||
|
#[error(display = "Packet identifier is invalid: {}", _0)]
|
||||||
|
InvalidPacketType(u8),
|
||||||
|
#[error(display = "Message identifier is invalid: {}", _0)]
|
||||||
|
InvalidMessageType(u8),
|
||||||
|
#[error(display = "Invalid SendProp type: {}", _0)]
|
||||||
|
InvalidSendPropType(u8),
|
||||||
|
#[error(display = "Invalid SendProp: {}", _0)]
|
||||||
|
InvalidSendProp(MalformedSendPropDefinitionError),
|
||||||
|
#[error(
|
||||||
|
display = "Unexpected amount of data left after parsing an object, {} bits remaining",
|
||||||
|
_0
|
||||||
|
)]
|
||||||
|
DataRemaining(usize),
|
||||||
|
#[error(display = "String table with index {} not found", _0)]
|
||||||
|
StringTableNotFound(u8),
|
||||||
|
#[error(display = "A malformed game event was read")]
|
||||||
|
MalformedGameEvent(#[error(cause)] GameEventError),
|
||||||
|
#[error(
|
||||||
|
display = "A read game event doesn't contain the expected values, expected type {} for {} event, got type {}",
|
||||||
|
expected_type,
|
||||||
|
name,
|
||||||
|
found_type
|
||||||
|
)]
|
||||||
|
InvalidGameEvent {
|
||||||
|
expected_type: GameEventValueType,
|
||||||
|
name: &'static str,
|
||||||
|
found_type: GameEventValueType,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum MalformedSendPropDefinitionError {
|
||||||
|
#[error(display = "Float property without defined size")]
|
||||||
|
UnsizedFloat,
|
||||||
|
#[error(display = "Array property without defined size")]
|
||||||
|
UnsizedArray,
|
||||||
|
#[error(display = "Array property without defined inner type")]
|
||||||
|
UntypedArray,
|
||||||
|
#[error(display = "Property used that can't be read")]
|
||||||
|
InvalidPropType,
|
||||||
|
#[error(display = "Array contents can't have the 'ChangesOften' flag")]
|
||||||
|
ArrayChangesOften,
|
||||||
|
#[error(display = "SendProp value out of range")]
|
||||||
|
OutOfRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
pub enum GameEventError {
|
pub enum GameEventError {
|
||||||
|
#[error(display = "Incorrect number of values")]
|
||||||
IncorrectValueCount,
|
IncorrectValueCount,
|
||||||
|
#[error(display = "Event with 'none' value")]
|
||||||
NoneValue,
|
NoneValue,
|
||||||
|
#[error(display = "Unknown type")]
|
||||||
UnknownType,
|
UnknownType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ReadError> for ParseError {
|
impl From<ReadError> for ParseError {
|
||||||
fn from(err: ReadError) -> ParseError {
|
fn from(err: ReadError) -> ParseError {
|
||||||
ParseError::ReadError(err)
|
match err {
|
||||||
|
ReadError::Utf8Error(utf8_error) => ParseError::MalformedUTF8(utf8_error),
|
||||||
|
_ => ParseError::ReadError(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,6 +121,24 @@ impl From<snap::Error> for ParseError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<MalformedDemoError> for ParseError {
|
||||||
|
fn from(err: MalformedDemoError) -> ParseError {
|
||||||
|
ParseError::MalformedDemo(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MalformedSendPropDefinitionError> for ParseError {
|
||||||
|
fn from(err: MalformedSendPropDefinitionError) -> ParseError {
|
||||||
|
ParseError::MalformedDemo(MalformedDemoError::InvalidSendProp(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<GameEventError> for ParseError {
|
||||||
|
fn from(err: GameEventError) -> ParseError {
|
||||||
|
ParseError::MalformedDemo(MalformedDemoError::MalformedGameEvent(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, ParseError>;
|
pub type Result<T> = std::result::Result<T, ParseError>;
|
||||||
|
|
||||||
pub trait Parse: Sized {
|
pub trait Parse: Sized {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@ use bitstream_reader::{BitRead, LittleEndian};
|
||||||
use enumflags2::BitFlags;
|
use enumflags2::BitFlags;
|
||||||
use enumflags2_derive::EnumFlags;
|
use enumflags2_derive::EnumFlags;
|
||||||
|
|
||||||
use crate::{Parse, ParseError, ReadResult, Result, Stream};
|
use crate::{MalformedDemoError, Parse, ParseError, ReadResult, Result, Stream};
|
||||||
|
|
||||||
use super::packet::datatable::ParseSendTable;
|
use super::packet::datatable::ParseSendTable;
|
||||||
use super::vector::{Vector, VectorXY};
|
use super::vector::{Vector, VectorXY};
|
||||||
use crate::demo::message::stringtable::log_base2;
|
use crate::demo::message::stringtable::log_base2;
|
||||||
use crate::demo::packet::datatable::SendTableName;
|
use crate::demo::packet::datatable::SendTableName;
|
||||||
|
use crate::demo::parser::MalformedSendPropDefinitionError;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
@ -236,9 +237,7 @@ impl SendPropValue {
|
||||||
Self::read_vector_xy(stream, definition).map(SendPropValue::from)
|
Self::read_vector_xy(stream, definition).map(SendPropValue::from)
|
||||||
}
|
}
|
||||||
SendPropType::Array => Self::read_array(stream, definition).map(SendPropValue::from),
|
SendPropType::Array => Self::read_array(stream, definition).map(SendPropValue::from),
|
||||||
_ => Err(ParseError::InvalidSendProp(
|
_ => Err(MalformedSendPropDefinitionError::InvalidPropType.into()),
|
||||||
"Prop type not allowed in entity",
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,7 +250,7 @@ impl SendPropValue {
|
||||||
let unsigned: u32 = stream.read()?;
|
let unsigned: u32 = stream.read()?;
|
||||||
unsigned
|
unsigned
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| ParseError::InvalidSendProp("SendProp value out of range"))
|
.map_err(|_| MalformedSendPropDefinitionError::OutOfRange.into())
|
||||||
} else {
|
} else {
|
||||||
stream.read().map_err(ParseError::from)
|
stream.read().map_err(ParseError::from)
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +264,7 @@ impl SendPropValue {
|
||||||
let num_bits = log_base2(
|
let num_bits = log_base2(
|
||||||
definition
|
definition
|
||||||
.element_count
|
.element_count
|
||||||
.ok_or(ParseError::InvalidSendProp("Unsized array"))?,
|
.ok_or(MalformedSendPropDefinitionError::UnsizedArray)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
let count = stream.read_int(num_bits as usize)?;
|
let count = stream.read_int(num_bits as usize)?;
|
||||||
|
|
@ -277,7 +276,7 @@ impl SendPropValue {
|
||||||
definition
|
definition
|
||||||
.array_property
|
.array_property
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or(ParseError::InvalidSendProp("Untyped array"))?,
|
.ok_or(MalformedSendPropDefinitionError::UntypedArray)?,
|
||||||
)?;
|
)?;
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
|
|
@ -321,13 +320,13 @@ impl SendPropValue {
|
||||||
} else {
|
} else {
|
||||||
let bit_count = definition
|
let bit_count = definition
|
||||||
.bit_count
|
.bit_count
|
||||||
.ok_or(ParseError::InvalidSendProp("Unsized float"))?;
|
.ok_or(MalformedSendPropDefinitionError::UnsizedFloat)?;
|
||||||
let high = definition
|
let high = definition
|
||||||
.high_value
|
.high_value
|
||||||
.ok_or(ParseError::InvalidSendProp("Unsized float"))?;
|
.ok_or(MalformedSendPropDefinitionError::UnsizedFloat)?;
|
||||||
let low = definition
|
let low = definition
|
||||||
.low_value
|
.low_value
|
||||||
.ok_or(ParseError::InvalidSendProp("Unsized float"))?;
|
.ok_or(MalformedSendPropDefinitionError::UnsizedFloat)?;
|
||||||
let raw: u32 = stream.read_int(bit_count as usize)?;
|
let raw: u32 = stream.read_int(bit_count as usize)?;
|
||||||
let percentage = (raw as f32) * get_frac_factor(bit_count as usize);
|
let percentage = (raw as f32) * get_frac_factor(bit_count as usize);
|
||||||
Ok(low + ((high - low) * percentage))
|
Ok(low + ((high - low) * percentage))
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ pub use bitstream_reader::Result as ReadResult;
|
||||||
pub use crate::demo::{
|
pub use crate::demo::{
|
||||||
message::MessageType,
|
message::MessageType,
|
||||||
parser::{
|
parser::{
|
||||||
DemoParser, GameEventError, MatchState, MessageTypeAnalyser, Parse, ParseError,
|
DemoParser, GameEventError, MalformedDemoError, MatchState, MessageTypeAnalyser, Parse,
|
||||||
ParserState, Result,
|
ParseError, ParserState, Result,
|
||||||
},
|
},
|
||||||
Demo, Stream,
|
Demo, Stream,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue