1use crate::Colour;
2
3#[derive(Clone, Debug, Eq, PartialEq)]
4pub struct Palette {
5 pub id: String,
6 pub name: Option<String>,
7 pub colours: Vec<Colour>,
8}
9
10impl Palette {
11 pub fn from_str(s: &str) -> Result<(Palette, Vec<crate::Error>), crate::Error> {
12 let mut lines: Vec<&str> = s.lines().collect();
13
14 if lines.is_empty() {
15 return Err(crate::Error::Palette);
16 }
17
18 let mut id = String::new();
19 let mut name = None;
20 let mut colours = Vec::new();
21 let mut warnings = Vec::new();
22
23 while !lines.is_empty() {
24 let line = lines.pop().unwrap();
25
26 if line.starts_with("PAL ") {
27 id = line.replace("PAL ", "");
28 } else if line.starts_with("NAME ") {
29 name = Some(line.replace("NAME ", ""));
30 } else {
31 let result = Colour::from(line);
32 if let Ok(colour) = result {
33 colours.push(colour)
34 } else {
35 warnings.push(result.unwrap_err());
36 }
37 }
38 }
39
40 colours.reverse();
41
42 Ok((Palette { id, name, colours }, warnings))
43 }
44}
45
46impl ToString for Palette {
47 fn to_string(&self) -> String {
48 let name = if self.name.as_ref().is_some() {
49 format!("NAME {}\n", self.name.as_ref().unwrap())
50 } else {
51 "".to_string()
52 };
53
54 let mut colours = String::new();
55 for colour in &self.colours {
56 colours.push_str(&format!("{}\n", colour.to_string()));
57 }
58 colours.pop();
59
60 format!("PAL {}\n{}{}", self.id, name, colours)
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use crate::{Colour, Palette};
67
68 #[test]
69 fn palette_from_string() {
70 let (output, _) = Palette::from_str("PAL 1\nNAME lamplight\n45,45,59\n66,60,39\n140,94,1").unwrap();
71
72 let expected = Palette {
73 id: "1".to_string(),
74 name: Some("lamplight".to_string()),
75 colours: vec![
76 Colour {
77 red: 45,
78 green: 45,
79 blue: 59,
80 },
81 Colour {
82 red: 66,
83 green: 60,
84 blue: 39,
85 },
86 Colour {
87 red: 140,
88 green: 94,
89 blue: 1,
90 },
91 ],
92 };
93
94 assert_eq!(output, expected);
95 }
96
97 #[test]
98 fn palette_from_string_no_name() {
99 let (output, _) = Palette::from_str("PAL 9\n45,45,59\n66,60,39\n140,94,1").unwrap();
100
101 let expected = Palette {
102 id: "9".to_string(),
103 name: None,
104 colours: vec![
105 Colour {
106 red: 45,
107 green: 45,
108 blue: 59,
109 },
110 Colour {
111 red: 66,
112 green: 60,
113 blue: 39,
114 },
115 Colour {
116 red: 140,
117 green: 94,
118 blue: 1,
119 },
120 ],
121 };
122
123 assert_eq!(output, expected);
124 }
125
126 #[test]
127 fn palette_to_string() {
128 let output = Palette {
129 id: "g".to_string(),
130 name: Some("moss".to_string()),
131 colours: vec![
132 Colour {
133 red: 1,
134 green: 2,
135 blue: 3,
136 },
137 Colour {
138 red: 255,
139 green: 254,
140 blue: 253,
141 },
142 Colour {
143 red: 126,
144 green: 127,
145 blue: 128,
146 },
147 ],
148 }.to_string();
149
150 let expected = "PAL g\nNAME moss\n1,2,3\n255,254,253\n126,127,128";
151 assert_eq!(output, expected);
152 }
153}