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

feature gate write support, use hash to compare game event definitions

This commit is contained in:
Robin Appelman 2025-07-14 16:05:30 +02:00
commit fbaca025b6
32 changed files with 6168 additions and 4363 deletions

View file

@ -1,7 +1,11 @@
use crate::demo::sendprop::{read_bit_coord, write_bit_coord};
use crate::demo::sendprop::read_bit_coord;
#[cfg(feature = "write")]
use crate::demo::sendprop::write_bit_coord;
use crate::demo::vector::Vector;
use crate::{ReadResult, Stream};
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
use bitbuffer::{BitRead, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream};
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
@ -44,6 +48,7 @@ impl BitRead<'_, LittleEndian> for BSPDecalMessage {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for BSPDecalMessage {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
let has_x = self.position.x != 0.0;
@ -75,6 +80,7 @@ impl BitWrite<LittleEndian> for BSPDecalMessage {
}
#[test]
#[cfg(feature = "write")]
fn test_decal_roundtrip() {
crate::test_roundtrip_write(BSPDecalMessage {
position: Vector::default(),

View file

@ -1,4 +1,6 @@
use bitbuffer::{BitRead, BitReadSized, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
use bitbuffer::{BitRead, BitReadSized, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream};
use serde::{Deserialize, Serialize};
use crate::demo::message::stringtable::log_base2;
@ -6,7 +8,8 @@ use crate::{ReadResult, Stream};
use std::cmp::min;
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitReadSized, BitWriteSized, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitReadSized, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWriteSized))]
pub struct ClassInfoEntry {
#[size = "input_size"]
class_id: u16,
@ -45,6 +48,7 @@ impl BitRead<'_, LittleEndian> for ClassInfoMessage {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for ClassInfoMessage {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
self.count.write(stream)?;
@ -61,6 +65,7 @@ impl BitWrite<LittleEndian> for ClassInfoMessage {
}
#[test]
#[cfg(feature = "write")]
fn test_class_info_roundtrip() {
crate::test_roundtrip_write(ClassInfoMessage {
count: 8,

View file

@ -1,4 +1,6 @@
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
use bitbuffer::{BitRead, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream};
use parse_display::Display;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
@ -7,7 +9,9 @@ use crate::demo::gameevent_gen::GameEventType;
use crate::demo::gamevent::{
GameEvent, GameEventDefinition, GameEventEntry, GameEventValueType, RawGameEvent,
};
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::{GameEventError, Parse, ParseError, ParserState, ReadResult, Result, Stream};
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
@ -52,6 +56,7 @@ impl Parse<'_> for GameEventMessage {
}
}
#[cfg(feature = "write")]
impl Encode for GameEventMessage {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
let definition = state
@ -68,6 +73,7 @@ impl Encode for GameEventMessage {
}
}
#[cfg(feature = "write")]
#[test]
fn test_game_event_roundtrip() {
use crate::demo::gameevent_gen::{GameInitEvent, ServerShutdownEvent};
@ -125,7 +131,6 @@ impl ParseBitSkip<'_> for GameEventMessage {
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(
BitRead,
BitWrite,
Debug,
Clone,
Copy,
@ -138,6 +143,7 @@ impl ParseBitSkip<'_> for GameEventMessage {
Serialize,
Deserialize,
)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct GameEventTypeId(#[size = 9] u16);
impl From<GameEventTypeId> for usize {
@ -179,6 +185,7 @@ impl BitRead<'_, LittleEndian> for GameEventDefinition {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for GameEventDefinition {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
self.id.write(stream)?;
@ -198,6 +205,7 @@ impl BitWrite<LittleEndian> for GameEventDefinition {
}
#[test]
#[cfg(feature = "write")]
fn test_event_definition_roundtrip() {
crate::test_roundtrip_write(GameEventDefinition {
id: GameEventTypeId(0),
@ -220,6 +228,7 @@ impl BitRead<'_, LittleEndian> for GameEventListMessage {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for GameEventListMessage {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
(self.event_list.len() as u16).write_sized(stream, 9)?;
@ -233,13 +242,17 @@ impl BitWrite<LittleEndian> for GameEventListMessage {
}
#[test]
#[cfg(feature = "write")]
fn test_event_list_roundtrip() {
crate::test_roundtrip_write(GameEventListMessage { event_list: vec![] });
crate::test_roundtrip_write(GameEventListMessage {
event_list: vec![GameEventDefinition {
id: GameEventTypeId(0),
event_type: GameEventType::ServerChangeLevelFailed,
entries: vec![GameEventEntry::new("level_name", GameEventValueType::String)],
entries: vec![GameEventEntry::new(
"level_name",
GameEventValueType::String,
)],
}],
});
crate::test_roundtrip_write(GameEventListMessage {

View file

@ -1,11 +1,14 @@
/// Messages that consists only of primitives and string and can be derived
use crate::demo::data::{MaybeUtf8String, ServerTick};
use crate::Stream;
use bitbuffer::{BitRead, BitWrite, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::BitWrite;
use bitbuffer::{BitRead, LittleEndian};
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct FileMessage {
pub transfer_id: u32,
pub file_name: String,
@ -13,7 +16,8 @@ pub struct FileMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct NetTickMessage {
pub tick: ServerTick,
pub frame_time: u16,
@ -21,13 +25,15 @@ pub struct NetTickMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct StringCmdMessage {
pub command: String,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[discriminant_bits = 8]
pub enum SignOnState {
None = 0,
@ -41,33 +47,38 @@ pub enum SignOnState {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct SignOnStateMessage {
pub state: SignOnState,
pub count: u32,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct PrintMessage {
pub value: MaybeUtf8String,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct SetPauseMessage {
pub pause: bool,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct SetViewMessage {
#[size = 11]
pub index: u16,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct FixAngleMessage {
pub relative: bool,
pub x: u16,
@ -76,7 +87,8 @@ pub struct FixAngleMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[endianness = "LittleEndian"]
#[serde(bound(deserialize = "'a: 'static"))]
pub struct EntityMessage<'a> {
@ -91,7 +103,8 @@ pub struct EntityMessage<'a> {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[endianness = "LittleEndian"]
#[serde(bound(deserialize = "'a: 'static"))]
pub struct MenuMessage<'a> {
@ -102,14 +115,16 @@ pub struct MenuMessage<'a> {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct GetCvarValueMessage {
pub cookie: u32,
pub value: String,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(BitRead, Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[endianness = "LittleEndian"]
#[serde(bound(deserialize = "'a: 'static"))]
pub struct CmdKeyValuesMessage<'a> {

View file

@ -11,9 +11,13 @@ pub use crate::demo::message::stringtable::*;
pub use crate::demo::message::tempentities::*;
pub use crate::demo::message::usermessage::*;
pub use crate::demo::message::voice::*;
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::{Parse, ParserState, Result, Stream};
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
use bitbuffer::BitRead;
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteStream, LittleEndian};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
@ -31,9 +35,8 @@ pub mod usermessage;
pub mod voice;
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema_repr))]
#[derive(
BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr,
)]
#[derive(BitRead, Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[repr(u8)]
#[discriminant_bits = 6]
pub enum MessageType {
@ -240,6 +243,7 @@ impl<'a> Message<'a> {
}
}
#[cfg(feature = "write")]
impl Encode for Message<'_> {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
match self {

View file

@ -1,13 +1,14 @@
use bitbuffer::{
BitRead, BitReadSized, BitReadStream, BitWrite, BitWriteSized, BitWriteStream, Endianness,
LittleEndian,
};
use bitbuffer::{BitRead, BitReadSized, BitReadStream, Endianness, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::borrow::Cow;
use crate::demo::packet::datatable::{ClassId, SendTable};
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::demo::sendprop::{SendProp, SendPropIdentifier, SendPropValue};
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use parse_display::{Display, FromStr};
@ -75,9 +76,8 @@ impl PartialOrd<u32> for EntityId {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema_repr))]
#[derive(
BitRead, BitWrite, Clone, Copy, Debug, PartialEq, Eq, Serialize_repr, Deserialize_repr,
)]
#[derive(BitRead, Clone, Copy, Debug, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[discriminant_bits = 2]
#[repr(u8)]
pub enum UpdateType {
@ -128,6 +128,7 @@ impl<E: Endianness> BitRead<'_, E> for BaselineIndex {
}
}
#[cfg(feature = "write")]
impl<E: Endianness> BitWrite<E> for BaselineIndex {
fn write(&self, stream: &mut BitWriteStream<E>) -> ReadResult<()> {
let val = match self {
@ -256,6 +257,7 @@ fn read_bit_var<'a, T: BitReadSized<'a, LittleEndian>>(stream: &mut Stream<'a>)
stream.read_sized(bits)
}
#[cfg(feature = "write")]
fn write_bit_var(var: u32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
let (ty, bits): (u8, usize) = if var >= 2u32.pow(12) {
(3, 32)
@ -272,6 +274,7 @@ fn write_bit_var(var: u32, stream: &mut BitWriteStream<LittleEndian>) -> ReadRes
}
#[test]
#[cfg(feature = "write")]
fn test_bit_var_roundtrip() {
use bitbuffer::{BitReadBuffer, BitReadStream};
@ -436,6 +439,7 @@ impl Parse<'_> for PacketEntitiesMessage {
}
}
#[cfg(feature = "write")]
impl Encode for PacketEntitiesMessage {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
self.max_entries.write_sized(stream, 11)?;
@ -520,6 +524,7 @@ impl PacketEntitiesMessage {
})
}
#[cfg(feature = "write")]
fn write_enter(
entity: &PacketEntity,
stream: &mut BitWriteStream<LittleEndian>,
@ -579,6 +584,7 @@ impl PacketEntitiesMessage {
Ok(())
}
#[cfg(feature = "write")]
pub fn write_update<'a, Props: IntoIterator<Item = &'a SendProp>>(
props: Props,
stream: &mut BitWriteStream<LittleEndian>,
@ -628,6 +634,7 @@ impl ParseBitSkip<'_> for PacketEntitiesMessage {
}
#[test]
#[cfg(feature = "write")]
fn test_packet_entity_message_roundtrip() {
use crate::demo::packet::datatable::{SendTable, SendTableName, ServerClass, ServerClassName};
use crate::demo::sendprop::{FloatDefinition, SendPropDefinition, SendPropParseDefinition};

View file

@ -1,5 +1,8 @@
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::{Parse, ParserState, Result, Stream};
#[cfg(feature = "write")]
use bitbuffer::{BitWriteStream, LittleEndian};
use serde::{Deserialize, Serialize};
@ -28,6 +31,7 @@ impl<'a> Parse<'a> for PreFetchMessage {
}
}
#[cfg(feature = "write")]
impl Encode for PreFetchMessage {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
let size = Self::bit_size(state.protocol_version);

View file

@ -1,6 +1,10 @@
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::{Parse, ParserState, Result, Stream};
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
use bitbuffer::{BitRead, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteStream};
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
@ -78,6 +82,7 @@ impl<'a> ParseBitSkip<'a> for ServerInfoMessage {
}
}
#[cfg(feature = "write")]
impl Encode for ServerInfoMessage {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
let part1 = ServerInfoMessagePart1 {
@ -118,7 +123,8 @@ impl Encode for ServerInfoMessage {
}
}
#[derive(BitRead, BitWrite)]
#[derive(BitRead)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct ServerInfoMessagePart1 {
pub version: u16,
pub server_count: u32,
@ -128,7 +134,8 @@ pub struct ServerInfoMessagePart1 {
pub max_classes: u16,
}
#[derive(BitRead, BitWrite)]
#[derive(BitRead)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct ServerInfoMessagePart2 {
pub player_slot: u8,
pub max_player_count: u8,

View file

@ -1,10 +1,13 @@
use bitbuffer::{BitRead, BitReadStream, BitWrite, BitWriteStream, Endianness};
use bitbuffer::{BitRead, BitReadStream, Endianness};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteStream};
use serde::{Deserialize, Serialize};
use crate::ReadResult;
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Debug, BitWrite, PartialEq, Serialize, Deserialize, Clone)]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct ConVar {
pub key: String,
pub value: String,
@ -30,6 +33,7 @@ pub struct SetConVarMessage {
pub vars: Vec<ConVar>,
}
#[cfg(feature = "write")]
impl<E: Endianness> BitWrite<E> for SetConVarMessage {
fn write(&self, stream: &mut BitWriteStream<E>) -> ReadResult<()> {
self.length.write(stream)?;
@ -37,6 +41,7 @@ impl<E: Endianness> BitWrite<E> for SetConVarMessage {
}
}
#[test]
#[cfg(feature = "write")]
fn test_set_con_var_roundtrip() {
crate::test_roundtrip_write(SetConVarMessage {
length: 0,

View file

@ -1,6 +1,6 @@
use bitbuffer::{
BitError, BitReadBuffer, BitReadStream, BitWrite, BitWriteSized, BitWriteStream, LittleEndian,
};
#[cfg(feature = "write")]
use bitbuffer::{BitError, BitWrite, BitWriteSized, BitWriteStream};
use bitbuffer::{BitReadBuffer, BitReadStream, LittleEndian};
use num_traits::{PrimInt, Unsigned};
use serde::{Deserialize, Serialize};
use snap::raw::{decompress_len, Decoder};
@ -9,7 +9,9 @@ use crate::demo::lzss::decompress;
use crate::demo::packet::stringtable::{
ExtraData, FixedUserDataSize, StringTable, StringTableEntry,
};
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use std::borrow::Cow;
use std::cmp::min;
@ -157,6 +159,7 @@ impl<'a> ParseBitSkip<'a> for CreateStringTableMessage<'a> {
}
}
#[cfg(feature = "write")]
impl Encode for CreateStringTableMessage<'_> {
fn encode(
&self,
@ -193,6 +196,7 @@ impl Encode for CreateStringTableMessage<'_> {
}
#[test]
#[cfg(feature = "write")]
fn test_create_string_table_roundtrip() {
let state = ParserState::new(24, |_| false, false);
crate::test_roundtrip_encode(
@ -274,6 +278,7 @@ impl<'a> ParseBitSkip<'a> for UpdateStringTableMessage<'a> {
}
}
#[cfg(feature = "write")]
impl Encode for UpdateStringTableMessage<'_> {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
self.table_id.write_sized(stream, 5)?;
@ -294,6 +299,7 @@ impl Encode for UpdateStringTableMessage<'_> {
}
#[test]
#[cfg(feature = "write")]
fn test_update_string_table_roundtrip() {
let mut state = ParserState::new(24, |_| false, false);
state.string_tables = vec![StringTableMeta {
@ -377,6 +383,7 @@ impl<'a> TableEntries<'a> {
self.entries
}
#[cfg(feature = "write")]
pub fn find_best_history(&self, text: &str) -> Option<(usize, usize)> {
let mut best_index = None;
let mut best_count = 0;
@ -394,6 +401,7 @@ impl<'a> TableEntries<'a> {
}
}
#[cfg(feature = "write")]
fn count_similar_characters(a: &str, b: &str) -> usize {
for (i, (a, b)) in a.bytes().zip(b.bytes()).enumerate() {
if a != b {
@ -429,6 +437,7 @@ pub fn parse_string_table_update<'a>(
Ok(entries.into_entries())
}
#[cfg(feature = "write")]
pub fn write_string_table_update(
entries: &[(u16, StringTableEntry)],
stream: &mut BitWriteStream<LittleEndian>,
@ -457,6 +466,7 @@ pub fn write_string_table_update(
}
#[test]
#[cfg(feature = "write")]
fn test_table_update_roundtrip() {
fn entry_roundtrip(
entries: Vec<(u16, StringTableEntry)>,
@ -601,6 +611,7 @@ fn read_table_entry<'a>(
Ok(StringTableEntry { text, extra_data })
}
#[cfg(feature = "write")]
fn write_table_entry(
entry: &StringTableEntry,
stream: &mut BitWriteStream<LittleEndian>,
@ -647,6 +658,7 @@ fn write_table_entry(
}
#[test]
#[cfg(feature = "write")]
fn test_table_entry_roundtrip() {
fn entry_roundtrip(entry: StringTableEntry, fixed_bits: Option<u8>) {
let table_meta = StringTableMeta {
@ -723,6 +735,7 @@ pub fn read_var_int(stream: &mut Stream) -> ReadResult<u32> {
Ok(result)
}
#[cfg(feature = "write")]
pub fn write_var_int(mut int: u32, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
while int > 0x7F {
let byte: u8 = int as u8 & 0x7F;
@ -734,6 +747,7 @@ pub fn write_var_int(mut int: u32, stream: &mut BitWriteStream<LittleEndian>) ->
// encode the int in such a way that it has a fixed size, but still decodes the same
// result is the first 40 bits of the return value
#[cfg(feature = "write")]
pub fn encode_var_int_fixed(mut int: u32) -> u64 {
let mut out = 0;
for i in 0..4 {
@ -746,6 +760,7 @@ pub fn encode_var_int_fixed(mut int: u32) -> u64 {
}
#[test]
#[cfg(feature = "write")]
fn test_var_int_roundtrip() {
fn var_int_roundtrip(int: u32) {
let mut data = Vec::new();
@ -768,6 +783,7 @@ fn test_var_int_roundtrip() {
}
#[test]
#[cfg(feature = "write")]
fn test_var_int_fixed_roundtrip() {
fn var_int_roundtrip(int: u32) {
let mut data = Vec::new();

View file

@ -1,11 +1,15 @@
use super::stringtable::read_var_int;
use crate::demo::message::packetentities::PacketEntitiesMessage;
use crate::demo::message::stringtable::{encode_var_int_fixed};
#[cfg(feature = "write")]
use crate::demo::message::stringtable::encode_var_int_fixed;
use crate::demo::packet::datatable::ClassId;
use crate::demo::parser::{Encode, ParseBitSkip};
#[cfg(feature = "write")]
use crate::demo::parser::Encode;
use crate::demo::parser::ParseBitSkip;
use crate::demo::sendprop::SendProp;
use crate::Result;
use crate::{Parse, ParseError, ParserState, Stream};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
use serde::{Deserialize, Serialize};
@ -95,6 +99,7 @@ impl ParseBitSkip<'_> for TempEntitiesMessage {
}
}
#[cfg(feature = "write")]
impl Encode for TempEntitiesMessage {
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
let count = match (self.events.len(), self.events.first()) {

View file

@ -1,4 +1,6 @@
use bitbuffer::{BitError, BitRead, BitWrite, BitWriteStream, Endianness, LittleEndian};
use bitbuffer::{BitError, BitRead, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteStream, Endianness};
use serde::{Deserialize, Serialize};
use crate::demo::data::MaybeUtf8String;
@ -6,7 +8,8 @@ use crate::demo::message::packetentities::EntityId;
use crate::{ReadResult, Stream};
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(BitRead, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[repr(u8)]
#[discriminant_bits = 8]
pub enum UserMessageType {
@ -157,6 +160,7 @@ impl<'a> BitRead<'a, LittleEndian> for UserMessage<'a> {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for UserMessage<'_> {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
self.message_type().write(stream)?;
@ -179,6 +183,7 @@ impl BitWrite<LittleEndian> for UserMessage<'_> {
}
#[test]
#[cfg(feature = "write")]
fn test_user_message_roundtrip() {
crate::test_roundtrip_write(UserMessage::Train(TrainMessage { data: 12 }));
crate::test_roundtrip_write(UserMessage::SayText2(Box::new(SayText2Message {
@ -222,6 +227,7 @@ impl BitRead<'_, LittleEndian> for ChatMessageKind {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for ChatMessageKind {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
match self {
@ -321,6 +327,7 @@ impl BitRead<'_, LittleEndian> for SayText2Message {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for SayText2Message {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
(u32::from(self.client) as u8).write(stream)?;
@ -340,6 +347,7 @@ impl BitWrite<LittleEndian> for SayText2Message {
}
#[test]
#[cfg(feature = "write")]
fn test_say_text2_roundtrip() {
crate::test_roundtrip_write(SayText2Message {
client: 3u32.into(),
@ -351,7 +359,8 @@ fn test_say_text2_roundtrip() {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[discriminant_bits = 8]
pub enum HudTextLocation {
PrintNotify = 1,
@ -361,7 +370,8 @@ pub enum HudTextLocation {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct TextMessage {
pub location: HudTextLocation,
pub text: MaybeUtf8String,
@ -375,19 +385,22 @@ impl TextMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct ResetHudMessage {
pub data: u8,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct TrainMessage {
pub data: u8,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct VoiceSubtitleMessage {
pub client: u8,
pub menu: u8,
@ -395,7 +408,8 @@ pub struct VoiceSubtitleMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct ShakeMessage {
pub command: u8,
pub amplitude: f32,
@ -412,6 +426,7 @@ pub struct VGuiMenuMessage {
pub data: Vec<VGuiMenuMessageData>,
}
#[cfg(feature = "write")]
impl<E: Endianness> BitWrite<E> for VGuiMenuMessage {
fn write(&self, stream: &mut BitWriteStream<E>) -> ReadResult<()> {
self.name.write(stream)?;
@ -425,14 +440,16 @@ impl<E: Endianness> BitWrite<E> for VGuiMenuMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct VGuiMenuMessageData {
pub key: MaybeUtf8String,
pub data: MaybeUtf8String,
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct RumbleMessage {
pub waveform_index: u8,
pub rumble_data: u8,
@ -440,7 +457,8 @@ pub struct RumbleMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct FadeMessage {
pub duration: u16,
pub hold: u16,
@ -449,7 +467,8 @@ pub struct FadeMessage {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
pub struct HapMeleeContactMessage {
pub data: u8,
}

View file

@ -1,4 +1,6 @@
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
use bitbuffer::{BitRead, LittleEndian};
#[cfg(feature = "write")]
use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream};
use serde::{Deserialize, Serialize};
use crate::{ReadResult, Stream};
@ -35,6 +37,7 @@ impl BitRead<'_, LittleEndian> for VoiceInitMessage {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for VoiceInitMessage {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
self.codec.write(stream)?;
@ -49,6 +52,7 @@ impl BitWrite<LittleEndian> for VoiceInitMessage {
}
#[test]
#[cfg(feature = "write")]
fn test_voice_init_roundtrip() {
crate::test_roundtrip_write(VoiceInitMessage {
codec: "foo".into(),
@ -63,7 +67,8 @@ fn test_voice_init_roundtrip() {
}
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(BitRead, BitWrite, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(BitRead, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "write", derive(BitWrite))]
#[endianness = "LittleEndian"]
#[serde(bound(deserialize = "'a: 'static"))]
pub struct VoiceDataMessage<'a> {
@ -104,6 +109,7 @@ impl<'a> BitRead<'a, LittleEndian> for ParseSoundsMessage<'a> {
}
}
#[cfg(feature = "write")]
impl BitWrite<LittleEndian> for ParseSoundsMessage<'_> {
fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
self.reliable.write(stream)?;
@ -124,6 +130,7 @@ impl BitWrite<LittleEndian> for ParseSoundsMessage<'_> {
}
#[test]
#[cfg(feature = "write")]
fn test_parse_sounds_roundtrip() {
use bitbuffer::BitReadBuffer;
let inner = BitReadBuffer::new(&[1, 2, 3, 4, 5, 6], LittleEndian);