vault 11.0.1

A parser for Company of Heroes replay files.
Documentation
use crate::data::ticks::{Message, Tick};
use crate::data::{ParserResult, Span};
use nom::combinator::{cut, map, peek};
use nom::multi::{length_data, length_value, many_m_n};
use nom::number::complete::le_u32;
use nom::sequence::tuple;

#[derive(Debug)]
pub struct MessageTick {
    _tick_type: u32,
    pub messages: Vec<Message>,
}

impl MessageTick {
    pub fn parse_tick(input: Span) -> ParserResult<Tick> {
        map(
            tuple((le_u32, length_value(le_u32, Self::parse_message))),
            |(tick_type, messages)| {
                Tick::Message(MessageTick {
                    _tick_type: tick_type,
                    messages,
                })
            },
        )(input)
    }

    fn parse_message(input: Span) -> ParserResult<Vec<Message>> {
        let (_, num_messages) = peek(le_u32)(input)?;

        if num_messages == 0 {
            Self::parse_empty_message(input)
        } else {
            Self::parse_content_message(input, num_messages)
        }
    }

    fn parse_empty_message(input: Span) -> ParserResult<Vec<Message>> {
        cut(map(tuple((le_u32, length_data(le_u32))), |(_, _)| {
            Vec::new()
        }))(input)
    }

    fn parse_content_message(input: Span, num_messages: u32) -> ParserResult<Vec<Message>> {
        cut(map(
            tuple((
                le_u32,
                le_u32,
                le_u32,
                le_u32,
                le_u32,
                many_m_n(1, num_messages as usize, Message::parse_message),
            )),
            |(_, _, _, _, _, messages)| messages,
        ))(input)
    }
}