tf_demo_parser/demo/parser/
mod.rs

1use crate::demo::data::DemoTick;
2use bitbuffer::{BitError, BitRead, BitWrite, BitWriteStream, LittleEndian};
3
4pub use self::messagetypeanalyser::MessageTypeAnalyser;
5
6use crate::demo::header::Header;
7
8use crate::demo::packet::Packet;
9use crate::demo::parser::analyser::Analyser;
10pub use crate::demo::parser::analyser::MatchState;
11pub use crate::demo::parser::handler::{DemoHandler, MessageHandler, NullHandler};
12pub use crate::demo::parser::state::ParserState;
13use crate::Stream;
14
15pub mod analyser;
16pub mod error;
17pub mod gamestateanalyser;
18pub mod handler;
19pub mod messagetypeanalyser;
20pub mod player_summary_analyzer;
21pub mod state;
22
23pub use self::error::*;
24use crate::demo::parser::handler::BorrowMessageHandler;
25
26pub trait Parse<'a>: Sized {
27    fn parse(stream: &mut Stream<'a>, state: &ParserState) -> Result<Self>;
28}
29
30impl<'a, T: BitRead<'a, LittleEndian>> Parse<'a> for T {
31    fn parse(stream: &mut Stream<'a>, _state: &ParserState) -> Result<Self> {
32        Self::read(stream).map_err(ParseError::from)
33    }
34}
35pub trait Encode: Sized {
36    fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()>;
37}
38
39impl<T: BitWrite<LittleEndian>> Encode for T {
40    fn encode(
41        &self,
42        stream: &mut BitWriteStream<LittleEndian>,
43        _state: &ParserState,
44    ) -> Result<()> {
45        self.write(stream).map_err(ParseError::from)
46    }
47}
48
49pub trait ParseBitSkip<'a> {
50    fn parse_skip(stream: &mut Stream<'a>, state: &ParserState) -> Result<()>;
51}
52
53impl<'a, T: BitRead<'a, LittleEndian>> ParseBitSkip<'a> for T {
54    #[inline(always)]
55    fn parse_skip(stream: &mut Stream<'a>, _state: &ParserState) -> Result<()> {
56        Self::skip(stream).map_err(ParseError::from)
57    }
58}
59
60pub struct DemoParser<'a, A: MessageHandler> {
61    handler: DemoHandler<'a, A>,
62    stream: Stream<'a>,
63}
64
65impl<'a> DemoParser<'a, Analyser> {
66    pub fn new(stream: Stream<'a>) -> Self {
67        DemoParser::new_with_analyser(stream, Analyser::new())
68    }
69
70    pub fn new_all(stream: Stream<'a>) -> Self {
71        DemoParser::new_all_with_analyser(stream, Analyser::new())
72    }
73}
74
75impl<'a, A: MessageHandler> DemoParser<'a, A> {
76    pub fn new_with_analyser(stream: Stream<'a>, analyser: A) -> Self {
77        DemoParser {
78            handler: DemoHandler::with_analyser(analyser),
79            stream,
80        }
81    }
82
83    pub fn new_all_with_analyser(stream: Stream<'a>, analyser: A) -> Self {
84        DemoParser {
85            handler: DemoHandler::parse_all_with_analyser(analyser),
86            stream,
87        }
88    }
89
90    pub fn parse(self) -> Result<(Header, A::Output)> {
91        let (header, mut ticker) = self.ticker()?;
92        while ticker.tick()? {
93            // noop
94        }
95        Ok((header, ticker.into_state()))
96    }
97
98    /// A Ticker provides a way to step trough the demo packet by packet
99    /// while allowing to see the intermediate states
100    pub fn ticker(mut self) -> Result<(Header, DemoTicker<'a, A>)> {
101        let header = Header::read(&mut self.stream)?;
102        self.handler.handle_header(&header);
103        let ticker = DemoTicker {
104            handler: self.handler,
105            packets: RawPacketStream::new(self.stream),
106        };
107        Ok((header, ticker))
108    }
109}
110
111#[derive(Clone)]
112pub struct RawPacketStream<'a> {
113    stream: Stream<'a>,
114    pub ended: bool,
115    pub incomplete: bool,
116}
117
118impl<'a> RawPacketStream<'a> {
119    pub fn new(stream: Stream<'a>) -> Self {
120        RawPacketStream {
121            stream,
122            ended: false,
123            incomplete: false,
124        }
125    }
126
127    pub fn pos(&self) -> usize {
128        self.stream.pos()
129    }
130
131    pub fn next(&mut self, state: &ParserState) -> Result<Option<Packet<'a>>> {
132        if self.ended {
133            Ok(None)
134        } else {
135            match Packet::parse(&mut self.stream, state) {
136                Ok(packet @ Packet::Stop(_)) => {
137                    self.ended = true;
138                    Ok(Some(packet))
139                }
140                Ok(packet) => Ok(Some(packet)),
141                Err(ParseError::ReadError(BitError::NotEnoughData { .. })) => {
142                    self.ended = true;
143                    self.incomplete = true;
144                    Ok(None)
145                }
146                Err(e) => {
147                    self.ended = true;
148                    Err(e)
149                }
150            }
151        }
152    }
153}
154
155#[derive(Clone)]
156pub struct DemoTicker<'a, A: MessageHandler> {
157    handler: DemoHandler<'a, A>,
158    packets: RawPacketStream<'a>,
159}
160
161impl<A: MessageHandler> DemoTicker<'_, A> {
162    /// Process the next packet
163    ///
164    /// returns whether or not there are still packets left in the demo
165    pub fn tick(&mut self) -> Result<bool> {
166        Ok(
167            if let Some(packet) = self.packets.next(&self.handler.state_handler)? {
168                self.handler.handle_packet(packet)?;
169
170                true
171            } else {
172                false
173            },
174        )
175    }
176
177    pub fn into_state(self) -> A::Output {
178        self.handler.into_output()
179    }
180}
181
182impl<A: MessageHandler + BorrowMessageHandler> DemoTicker<'_, A> {
183    pub fn state(&self) -> &A::Output {
184        self.handler.borrow_output()
185    }
186
187    pub fn parser_state(&self) -> &ParserState {
188        self.handler.get_parser_state()
189    }
190
191    /// Process the next packet
192    #[allow(clippy::should_implement_trait)]
193    pub fn next(&mut self) -> Result<Option<Tick<A::Output>>> {
194        Ok(
195            if let Some(packet) = self.packets.next(&self.handler.state_handler)? {
196                let tick = packet.tick();
197                self.handler.handle_packet(packet)?;
198
199                Some(Tick {
200                    state: self.handler.borrow_output(),
201                    parser_state: self.handler.get_parser_state(),
202                    tick,
203                })
204            } else {
205                None
206            },
207        )
208    }
209}
210
211pub struct Tick<'a, State> {
212    pub state: &'a State,
213    pub parser_state: &'a ParserState,
214    pub tick: DemoTick,
215}