mirror of
https://codeberg.org/demostf/parser.git
synced 2026-10-01 08:44:05 +02:00
180 lines
6.3 KiB
Rust
180 lines
6.3 KiB
Rust
use bitbuffer::BitRead;
|
|
#[cfg(feature = "write")]
|
|
use bitbuffer::{BitWrite, BitWriteStream, LittleEndian};
|
|
|
|
use crate::{Parse, ParserState, Result, Stream};
|
|
|
|
use self::consolecmd::ConsoleCmdPacket;
|
|
use self::datatable::DataTablePacket;
|
|
use self::message::MessagePacket;
|
|
use self::stop::StopPacket;
|
|
use self::stringtable::StringTablePacket;
|
|
use self::synctick::SyncTickPacket;
|
|
use self::usercmd::UserCmdPacket;
|
|
use crate::demo::data::DemoTick;
|
|
#[cfg(feature = "write")]
|
|
use crate::demo::parser::Encode;
|
|
use serde::{Deserialize, Serialize};
|
|
#[cfg(feature = "trace")]
|
|
use tracing::{Level, event, span};
|
|
|
|
pub mod consolecmd;
|
|
pub mod datatable;
|
|
pub mod message;
|
|
pub mod stop;
|
|
pub mod stringtable;
|
|
pub mod synctick;
|
|
pub mod usercmd;
|
|
|
|
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
#[serde(bound(deserialize = "'a: 'static"))]
|
|
#[serde(tag = "type")]
|
|
pub enum Packet<'a> {
|
|
Signon(MessagePacket<'a>),
|
|
Message(MessagePacket<'a>),
|
|
SyncTick(SyncTickPacket),
|
|
ConsoleCmd(ConsoleCmdPacket),
|
|
UserCmd(UserCmdPacket),
|
|
DataTables(DataTablePacket),
|
|
Stop(StopPacket),
|
|
StringTables(StringTablePacket<'a>),
|
|
}
|
|
|
|
impl Packet<'_> {
|
|
pub fn tick(&self) -> DemoTick {
|
|
match self {
|
|
Packet::Signon(msg) => msg.tick,
|
|
Packet::Message(msg) => msg.tick,
|
|
Packet::SyncTick(msg) => msg.tick,
|
|
Packet::ConsoleCmd(msg) => msg.tick,
|
|
Packet::UserCmd(msg) => msg.tick,
|
|
Packet::DataTables(msg) => msg.tick,
|
|
Packet::Stop(msg) => msg.tick,
|
|
Packet::StringTables(msg) => msg.tick,
|
|
}
|
|
}
|
|
|
|
pub fn set_tick(&mut self, tick: DemoTick) {
|
|
match self {
|
|
Packet::Signon(msg) => msg.tick = tick,
|
|
Packet::Message(msg) => msg.tick = tick,
|
|
Packet::SyncTick(msg) => msg.tick = tick,
|
|
Packet::ConsoleCmd(msg) => msg.tick = tick,
|
|
Packet::UserCmd(msg) => msg.tick = tick,
|
|
Packet::DataTables(msg) => msg.tick = tick,
|
|
Packet::Stop(msg) => msg.tick = tick,
|
|
Packet::StringTables(msg) => msg.tick = tick,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
|
#[derive(BitRead, Debug, Clone, Copy, Eq, PartialEq)]
|
|
#[cfg_attr(feature = "write", derive(BitWrite))]
|
|
#[discriminant_bits = 8]
|
|
#[repr(u8)]
|
|
pub enum PacketType {
|
|
Signon = 1,
|
|
Message = 2,
|
|
SyncTick = 3,
|
|
ConsoleCmd = 4,
|
|
UserCmd = 5,
|
|
DataTables = 6,
|
|
Stop = 7,
|
|
StringTables = 8,
|
|
}
|
|
|
|
impl Packet<'_> {
|
|
pub fn packet_type(&self) -> PacketType {
|
|
match self {
|
|
Packet::Signon(_) => PacketType::Signon,
|
|
Packet::Message(_) => PacketType::Message,
|
|
Packet::SyncTick(_) => PacketType::SyncTick,
|
|
Packet::ConsoleCmd(_) => PacketType::ConsoleCmd,
|
|
Packet::UserCmd(_) => PacketType::UserCmd,
|
|
Packet::DataTables(_) => PacketType::DataTables,
|
|
Packet::Stop(_) => PacketType::Stop,
|
|
Packet::StringTables(_) => PacketType::StringTables,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Parse<'a> for Packet<'a> {
|
|
fn parse(stream: &mut Stream<'a>, state: &ParserState) -> Result<Self> {
|
|
let packet_type = PacketType::read(stream)?;
|
|
#[cfg(feature = "trace")]
|
|
{
|
|
let tick: u32 = if packet_type == PacketType::Stop {
|
|
0
|
|
} else {
|
|
let tick = stream.read()?;
|
|
stream.set_pos(stream.pos() - 32)?;
|
|
tick
|
|
};
|
|
let _span =
|
|
span!(Level::INFO, "reading packet", packet_type = ?packet_type, tick = tick)
|
|
.entered();
|
|
event!(Level::DEBUG, "parsing packet");
|
|
}
|
|
Ok(match packet_type {
|
|
PacketType::Signon => Packet::Signon(MessagePacket::parse(stream, state)?),
|
|
PacketType::Message => Packet::Message(MessagePacket::parse(stream, state)?),
|
|
PacketType::SyncTick => Packet::SyncTick(SyncTickPacket::parse(stream, state)?),
|
|
PacketType::ConsoleCmd => Packet::ConsoleCmd(ConsoleCmdPacket::parse(stream, state)?),
|
|
PacketType::UserCmd => Packet::UserCmd(UserCmdPacket::parse(stream, state)?),
|
|
PacketType::DataTables => Packet::DataTables(DataTablePacket::parse(stream, state)?),
|
|
PacketType::Stop => Packet::Stop(StopPacket::parse(stream, state)?),
|
|
PacketType::StringTables => {
|
|
Packet::StringTables(StringTablePacket::parse(stream, state)?)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "write")]
|
|
impl Encode for Packet<'_> {
|
|
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
|
|
#[cfg(feature = "trace")]
|
|
let _span = span!(Level::INFO, "encoding packet", packet_type = ?self.packet_type(), tick = ?self.tick()).entered();
|
|
self.packet_type().write(stream)?;
|
|
match self {
|
|
Packet::Signon(inner) => inner.encode(stream, state),
|
|
Packet::Message(inner) => inner.encode(stream, state),
|
|
Packet::SyncTick(inner) => inner.encode(stream, state),
|
|
Packet::ConsoleCmd(inner) => inner.encode(stream, state),
|
|
Packet::UserCmd(inner) => inner.encode(stream, state),
|
|
Packet::DataTables(inner) => inner.encode(stream, state),
|
|
Packet::Stop(inner) => inner.encode(stream, state),
|
|
Packet::StringTables(inner) => inner.encode(stream, state),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PacketType {
|
|
pub fn as_str(&self) -> &'static str {
|
|
match self {
|
|
PacketType::Signon => "Signon",
|
|
PacketType::Message => "Message",
|
|
PacketType::SyncTick => "SyncTick",
|
|
PacketType::ConsoleCmd => "ConsoleCmd",
|
|
PacketType::UserCmd => "UserCmd",
|
|
PacketType::DataTables => "DataTables",
|
|
PacketType::Stop => "Stop",
|
|
PacketType::StringTables => "StringTables",
|
|
}
|
|
}
|
|
|
|
pub fn as_lowercase_str(&self) -> &'static str {
|
|
match self {
|
|
PacketType::Signon => "signon",
|
|
PacketType::Message => "message",
|
|
PacketType::SyncTick => "synctick",
|
|
PacketType::ConsoleCmd => "consolecmd",
|
|
PacketType::UserCmd => "usercmd",
|
|
PacketType::DataTables => "datatables",
|
|
PacketType::Stop => "stop",
|
|
PacketType::StringTables => "stringtables",
|
|
}
|
|
}
|
|
}
|