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}