chart_file_parser/
track.rs

1use std::fmt::Display;
2
3use nom::{
4    character::complete::{alpha1, multispace1},
5    combinator::map,
6    multi::separated_list1,
7    sequence::tuple,
8    IResult,
9};
10
11use crate::{
12    components::{curlied, spaced, squared},
13    track_event::TrackEvent,
14};
15
16#[derive(Debug, PartialEq, Eq)]
17pub struct Track<'a> {
18    name: &'a str,
19    events: Vec<TrackEvent<'a>>,
20}
21
22impl<'a> Track<'a> {
23    #[must_use]
24    pub(crate) fn new(name: &'a str, events: Vec<TrackEvent<'a>>) -> Self {
25        Self { name, events }
26    }
27
28    pub(crate) fn multiply(&mut self, factor: u32) {
29        for item in &mut self.events {
30            item.multiply(factor);
31        }
32    }
33
34    #[inline]
35    pub(crate) fn parse(input: &str) -> IResult<&str, Track> {
36        map(
37            tuple((
38                spaced(squared(alpha1)),
39                curlied(spaced(separated_list1(multispace1, TrackEvent::parse))),
40            )),
41            |(name, events)| Track::new(name, events),
42        )(input)
43    }
44}
45
46impl<'a> Display for Track<'a> {
47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        write!(
49            f,
50            "[{}]\n{{\n{}}}\n",
51            self.name,
52            self.events
53                .iter()
54                .map(TrackEvent::to_string)
55                .collect::<String>()
56        )
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    #![allow(clippy::unwrap_used)]
63    use super::*;
64
65    #[test]
66    fn test_track() {
67        Track::parse(include_str!("test_data/test_track.txt")).unwrap();
68    }
69}