use crate::error::S2ProtocolError;
use crate::SC2EventType;
use crate::tracker_events::TrackerEvent;
use crate::versions::protocol75689::byte_aligned::ReplayTrackerEEventId as Protocol75689ReplayTrackerEEventId;
use crate::versions::protocol87702::byte_aligned::ReplayTrackerEEventId as Protocol87702ReplayTrackerEEventId;
use nom::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct TrackertEventIteratorState {
event_data: Vec<u8>,
event_loop: i64,
byte_index: usize,
}
impl From<Vec<u8>> for TrackertEventIteratorState {
fn from(event_data: Vec<u8>) -> Self {
Self {
event_data,
event_loop: 0,
byte_index: 0,
}
}
}
impl TrackertEventIteratorState {
pub fn read_versioned_tracker_event(
&mut self,
protocol_version: u32,
) -> Result<TrackerEvent, S2ProtocolError> {
let (delta, event) = match protocol_version {
0..=75689 => {
let (tail, (delta, event)) = Protocol75689ReplayTrackerEEventId::parse_event_pair(
&self.event_data[self.byte_index..],
)?;
self.byte_index +=
tail.as_ptr() as usize - self.event_data[self.byte_index..].as_ptr() as usize;
self.event_loop += delta as i64;
(delta, event.try_into()?)
}
_ => {
let (tail, (delta, event)) = Protocol87702ReplayTrackerEEventId::parse_event_pair(
&self.event_data[self.byte_index..],
)?;
self.byte_index +=
tail.as_ptr() as usize - self.event_data[self.byte_index..].as_ptr() as usize;
self.event_loop += delta as i64;
(delta, event.try_into()?)
}
};
Ok(TrackerEvent { delta, event })
}
#[tracing::instrument(level = "debug", skip(self), fields(event_loop = self.event_loop))]
pub fn get_next_event(&mut self, protocol_version: u32) -> Option<SC2EventType> {
loop {
let current_slice: &[u8] = &self.event_data[self.byte_index..];
if current_slice.input_len() == 0 {
return None;
}
match self.read_versioned_tracker_event(protocol_version) {
Ok(val) => {
let tracker_loop = self.event_loop;
let event = SC2EventType::Tracker {
tracker_loop,
event: val.event.clone(),
};
return Some(event);
}
Err(S2ProtocolError::UnsupportedEventType) => {}
Err(err) => {
tracing::error!("Error reading tracker event: {:?}", err);
return None;
}
}
}
}
}