faf_replay_parser/iter/
verify.rs

1use crate::reader::ReplayReadError;
2use crate::replay::ReplayCommandFrameSpan;
3use crate::version::Version;
4use crate::ReplayResult;
5use std::convert::TryFrom;
6
7/// Checks that the command id and size field are valid. This is intended to be used with the
8/// [`BytesCommandIter`](trait.BytesCommandIter.html) trait.
9///
10/// # Errors
11/// If either check fails, a `ReplayReadError::Malformed` is returned.
12pub fn verify_frame_header<V: Version>(
13    frame: ReplayCommandFrameSpan,
14) -> ReplayResult<ReplayCommandFrameSpan> {
15    if let Err(_) = V::CommandId::try_from(frame.cmd) {
16        return Err(ReplayReadError::Malformed("invalid command"));
17    }
18    if frame.size < 3 {
19        return Err(ReplayReadError::Malformed("invalid command size"));
20    }
21    return Ok(frame);
22}
23
24/// An iterator adapter for checking the validity of command frame headers.
25///
26/// See [`verify_frame_header`].
27pub struct VerifyFrame<'a, V, I>
28where
29    V: Version,
30    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
31{
32    iter: I,
33    phantom: std::marker::PhantomData<V>,
34}
35impl<'a, V, I> VerifyFrame<'a, V, I>
36where
37    V: Version,
38    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
39{
40    pub fn new(iter: I) -> VerifyFrame<'a, V, I> {
41        VerifyFrame {
42            iter,
43            phantom: std::marker::PhantomData,
44        }
45    }
46}
47
48impl<'a, V, I> Iterator for VerifyFrame<'a, V, I>
49where
50    V: Version,
51    I: Iterator<Item = ReplayCommandFrameSpan<'a>>,
52{
53    type Item = ReplayResult<ReplayCommandFrameSpan<'a>>;
54
55    fn next(&mut self) -> Option<Self::Item> {
56        self.iter.next().map(verify_frame_header::<V>)
57    }
58
59    fn size_hint(&self) -> (usize, Option<usize>) {
60        self.iter.size_hint()
61    }
62}