1use crate::optional_data_line;
2
3use std::fmt;
4
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct Dialogue {
7 pub id: String,
8 pub contents: String,
9 pub name: Option<String>,
10}
11
12impl Dialogue {
13 pub fn from_str(str: &str) -> Result<Dialogue, crate::Error> {
14 let mut lines: Vec<&str> = str.lines().collect();
15
16 if lines.is_empty() || !lines[0].starts_with("DLG ") {
17 return Err(crate::Error::Dialogue);
18 }
19
20 let id = lines[0].replace("DLG ", "");
21
22 let last_line = lines.pop().unwrap();
23
24 let name = if last_line.starts_with("NAME ") {
25 Some(last_line.replace("NAME ", ""))
26 } else {
27 lines.push(last_line);
28 None
29 };
30
31 let contents = lines[1..].join("\n");
32
33 Ok(Dialogue { id, contents, name })
34 }
35}
36
37impl fmt::Display for Dialogue {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(
40 f,
41 "DLG {}\n{}{}",
42 self.id,
43 self.contents,
44 optional_data_line("NAME", self.name.as_ref())
45 )
46 }
47}
48
49#[cfg(test)]
50mod test {
51 use crate::Dialogue;
52
53 #[test]
54 fn dialogue_from_str() {
55 let output = Dialogue::from_str(
56 "DLG h\nhello\nNAME not a dialogue name\nNAME a dialogue name"
57 ).unwrap();
58
59 let expected = Dialogue {
60 id: "h".to_string(),
61 contents: "hello\nNAME not a dialogue name".to_string(),
62 name: Some("a dialogue name".to_string())
63 };
64
65 assert_eq!(output, expected);
66 }
67
68 #[test]
69 fn dialogue_to_string() {
70 let output = Dialogue {
71 id: "y".to_string(),
72 contents: "This is a bit of dialogue,\nblah blah\nblah blah".to_string(),
73 name: Some("a dialogue name".to_string())
74 }.to_string();
75
76 let expected = "DLG y\nThis is a bit of dialogue,\nblah blah\nblah blah\nNAME a dialogue name";
77
78 assert_eq!(output, expected);
79 }
80}