bitsy_parser/
item.rs

1use crate::{optional_data_line, AnimationFrames, Image};
2use crate::image::animation_frames_from_str;
3use std::fmt;
4
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct Item {
7    pub id: String,
8    pub animation_frames: Vec<Image>,
9    pub name: Option<String>,
10    pub dialogue_id: Option<String>,
11    pub colour_id: Option<u64>,
12}
13
14impl Item {
15    fn name_line(&self) -> String {
16        optional_data_line("NAME", self.name.as_ref())
17    }
18
19    fn dialogue_line(&self) -> String {
20        optional_data_line("DLG", self.dialogue_id.as_ref())
21    }
22
23    fn colour_line(&self) -> String {
24        optional_data_line("COL", self.colour_id.as_ref())
25    }
26
27    pub fn from_str(str: &str) -> Result<Item, crate::Error> {
28        let mut lines: Vec<&str> = str.lines().collect();
29
30        if lines.is_empty() || !lines[0].starts_with("ITM ") {
31            return Err(crate::Error::Item);
32        }
33
34        let id = lines[0].replace("ITM ", "");
35        let mut name = None;
36        let mut dialogue_id = None;
37        let mut colour_id: Option<u64> = None;
38
39        loop {
40            let last_line = lines.pop().unwrap();
41
42            if last_line.starts_with("NAME") {
43                name = Some(last_line.replace("NAME ", "").to_string());
44            } else if last_line.starts_with("DLG") {
45                dialogue_id = Some(last_line.replace("DLG ", "").to_string());
46            } else if last_line.starts_with("COL") {
47                colour_id = Some(last_line.replace("COL ", "").parse().unwrap());
48            } else {
49                lines.push(last_line);
50                break;
51            }
52        }
53
54        let animation_frames = animation_frames_from_str(
55            &lines[1..].join("\n")
56        );
57
58        Ok(Item { id, name, animation_frames, dialogue_id, colour_id })
59    }
60}
61
62impl fmt::Display for Item {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(
65            f,
66            "ITM {}\n{}{}{}{}",
67            self.id,
68            self.animation_frames.to_string(),
69            self.name_line(),
70            self.dialogue_line(),
71            self.colour_line(),
72        )
73    }
74}
75
76#[cfg(test)]
77mod test {
78    use crate::{Item, mock};
79
80    #[test]
81    fn item_from_string() {
82        let output = Item::from_str(include_str!("test-resources/item")).unwrap();
83        let expected = mock::item();
84        assert_eq!(output, expected);
85    }
86
87    #[test]
88    fn item_to_string() {
89        let output = mock::item().to_string();
90        let expected = include_str!("test-resources/item").to_string();
91        assert_eq!(output, expected);
92    }
93}