wotbreplay_parser/models/data/
packet.rs

1use std::io::Read;
2
3use byteorder::{LittleEndian, ReadBytesExt};
4use serde::Serialize;
5use serde_with::serde_as;
6
7use crate::models::data::payload::Payload;
8use crate::result::Result;
9use crate::Error;
10
11/// «Packet» is a single traffic message in a replay,
12/// packets tell us what is going on during the battle.
13#[serde_as]
14#[derive(Debug, Serialize)]
15pub struct Packet {
16    /// Replay time, starting from zero.
17    #[serde(rename = "clock")]
18    pub clock_secs: f32,
19
20    /// Parsed packet payload.
21    pub payload: Payload,
22
23    /// Raw packet payload, excluding the clock and packet type, and including optional subtype.
24    ///
25    /// This attribute requires the `raw-payload` feature.
26    #[cfg(feature = "raw-payload")]
27    #[serde_as(as = "serde_with::hex::Hex")]
28    pub raw_payload: Vec<u8>,
29}
30
31impl Packet {
32    /// Parse next packet from the reader.
33    ///
34    /// # Returns
35    ///
36    /// Parsed packet, or [`None`], when no packets are left.
37    pub fn from_reader(reader: &mut impl Read) -> Result<Option<Self>> {
38        let Ok(length) = reader.read_u32::<LittleEndian>() else {
39            return Ok(None);
40        };
41        let type_ = reader.read_u32::<LittleEndian>()?;
42        let clock_secs = reader.read_f32::<LittleEndian>()?;
43        let raw_payload = Self::read_raw_payload(reader, length as usize)?;
44        let payload = Payload::new(type_, &raw_payload).map_err(|source| {
45            Error::PacketPayloadParsingError {
46                source: Box::new(source),
47                type_,
48                clock_secs,
49            }
50        })?;
51        let this = Self {
52            clock_secs,
53            payload,
54
55            #[cfg(feature = "raw-payload")]
56            raw_payload,
57        };
58        Ok(Some(this))
59    }
60
61    fn read_raw_payload(reader: &mut impl Read, length: usize) -> Result<Vec<u8>> {
62        let mut buffer = vec![0; length];
63        reader.read_exact(&mut buffer)?;
64        Ok(buffer)
65    }
66}