faf_replay_parser/iter/
parse.rs

1use crate::iter::verify_frame_header;
2use crate::replay::ReplayCommandFrameSpan;
3use crate::version::{Command, Version};
4use crate::ReplayResult;
5
6/// Parse some command data into a `Command`. This is intended to be used with the
7/// [`BytesCommandIter`](trait.BytesCommandIter.html) trait.
8///
9/// # Errors
10/// Returns a `ReplayReadError` if the command data can't be parsed or is too short.
11pub fn parse_command<V: Version>(frame: ReplayCommandFrameSpan) -> ReplayResult<V::Command> {
12    // This validation already happens during parsing as a necessity
13    debug_assert!(frame.data.len() >= 3);
14
15    V::Command::parse_command_data(frame.cmd, &frame.data[3..])
16}
17
18/// An iterator adapter for parsing command frame headers into `Command`s. This also verifies
19/// the contents of the frame headers first, returning any errors.
20///
21/// See [`CommandFrameAdapters::parse_commands`](trait.CommandFrameAdapters.html#method.parse_commands).
22pub struct ParseCommand<'a, V, I>
23where
24    V: Version,
25    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
26{
27    iter: I,
28    phantom: std::marker::PhantomData<V>,
29}
30impl<'a, V, I> ParseCommand<'a, V, I>
31where
32    V: Version,
33    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
34{
35    pub fn new(iter: I) -> ParseCommand<'a, V, I> {
36        ParseCommand {
37            iter,
38            phantom: std::marker::PhantomData,
39        }
40    }
41}
42
43impl<'a, V, I> Iterator for ParseCommand<'a, V, I>
44where
45    V: Version,
46    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
47{
48    type Item = ReplayResult<V::Command>;
49
50    #[inline]
51    fn next(&mut self) -> Option<Self::Item> {
52        self.iter
53            .next()
54            .map(verify_frame_header::<V>)
55            .map(|result| result.and_then(parse_command::<V>))
56    }
57
58    #[inline]
59    fn size_hint(&self) -> (usize, Option<usize>) {
60        self.iter.size_hint()
61    }
62}
63
64/// An iterator adapter for parsing command frame headers into `Command`s.
65///
66/// Note that this does not verify the validity of the command frame headers.
67///
68/// See [`CommandFrameAdapters::parse_command_data`](trait.CommandFrameAdapters.html#method.parse_command_data).
69pub struct ParseCommandData<'a, V, I>
70where
71    V: Version,
72    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
73{
74    iter: I,
75    phantom: std::marker::PhantomData<V>,
76}
77impl<'a, V, I> ParseCommandData<'a, V, I>
78where
79    V: Version,
80    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
81{
82    pub fn new(iter: I) -> ParseCommandData<'a, V, I> {
83        ParseCommandData {
84            iter,
85            phantom: std::marker::PhantomData,
86        }
87    }
88}
89
90impl<'a, V, I> Iterator for ParseCommandData<'a, V, I>
91where
92    V: Version,
93    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
94{
95    type Item = ReplayResult<V::Command>;
96
97    fn next(&mut self) -> Option<Self::Item> {
98        self.iter.next().map(parse_command::<V>)
99    }
100
101    fn size_hint(&self) -> (usize, Option<usize>) {
102        self.iter.size_hint()
103    }
104}