1use super::generated_api::api::style::{
2 color::Payload as ProtobufColorPayload, Color as ProtobufColor, ColorType as ProtobufColorType,
3 Palette as ProtobufPalette, RgbColorPayload as ProtobufRgbColorPayload, Style as ProtobufStyle,
4 Styling as ProtobufStyling, ThemeHue as ProtobufThemeHue,
5};
6use crate::data::{
7 MultiplayerColors, Palette, PaletteColor, Style, StyleDeclaration, Styling, ThemeHue,
8};
9use crate::errors::prelude::*;
10
11use std::convert::TryFrom;
12
13impl TryFrom<ProtobufStyle> for Style {
14 type Error = &'static str;
15 fn try_from(protobuf_style: ProtobufStyle) -> Result<Self, &'static str> {
16 let s = protobuf_style
17 .styling
18 .ok_or("malformed style payload")?
19 .try_into()?;
20 Ok(Style {
21 colors: s,
22 rounded_corners: protobuf_style.rounded_corners,
23 hide_session_name: protobuf_style.hide_session_name,
24 })
25 }
26}
27
28#[allow(deprecated)]
29impl TryFrom<Style> for ProtobufStyle {
30 type Error = &'static str;
31 fn try_from(style: Style) -> Result<Self, &'static str> {
32 let s = ProtobufStyling::try_from(style.colors)?;
33 let palette = Palette::try_from(style.colors).map_err(|_| "malformed style payload")?;
34 Ok(ProtobufStyle {
35 palette: Some(palette.try_into()?),
36 rounded_corners: style.rounded_corners,
37 hide_session_name: style.hide_session_name,
38 styling: Some(s),
39 })
40 }
41}
42
43fn to_array<T, const N: usize>(v: Vec<T>) -> std::result::Result<[T; N], &'static str> {
44 v.try_into()
45 .map_err(|_| "Could not obtain array from protobuf field")
46}
47
48fn to_style_declaration(
49 parsed_array: Result<[PaletteColor; 6], &'static str>,
50) -> Result<StyleDeclaration, &'static str> {
51 parsed_array.map(|arr| StyleDeclaration {
52 base: arr[0],
53 background: arr[1],
54 emphasis_0: arr[2],
55 emphasis_1: arr[3],
56 emphasis_2: arr[4],
57 emphasis_3: arr[5],
58 })
59}
60
61fn to_multiplayer_colors(
62 parsed_array: Result<[PaletteColor; 10], &'static str>,
63) -> Result<MultiplayerColors, &'static str> {
64 parsed_array.map(|arr| MultiplayerColors {
65 player_1: arr[0],
66 player_2: arr[1],
67 player_3: arr[2],
68 player_4: arr[3],
69 player_5: arr[4],
70 player_6: arr[5],
71 player_7: arr[6],
72 player_8: arr[7],
73 player_9: arr[8],
74 player_10: arr[9],
75 })
76}
77
78#[macro_export]
79macro_rules! color_definitions {
80 ($proto:expr, $declaration:ident, $size:expr) => {
81 to_style_declaration(to_array::<PaletteColor, $size>(
82 $proto
83 .$declaration
84 .into_iter()
85 .map(PaletteColor::try_from)
86 .collect::<Result<Vec<PaletteColor>, _>>()?,
87 ))?
88 };
89}
90
91#[macro_export]
92macro_rules! multiplayer_colors {
93 ($proto:expr, $size: expr) => {
94 to_multiplayer_colors(to_array::<PaletteColor, $size>(
95 $proto
96 .multiplayer_user_colors
97 .into_iter()
98 .map(PaletteColor::try_from)
99 .collect::<Result<Vec<PaletteColor>, _>>()?,
100 ))?
101 };
102}
103
104impl TryFrom<ProtobufStyling> for Styling {
105 type Error = &'static str;
106
107 fn try_from(proto: ProtobufStyling) -> std::result::Result<Self, Self::Error> {
108 let frame_unselected = if proto.frame_unselected.len() > 0 {
109 Some(color_definitions!(proto, frame_unselected, 6))
110 } else {
111 None
112 };
113
114 Ok(Styling {
115 text_unselected: color_definitions!(proto, text_unselected, 6),
116 text_selected: color_definitions!(proto, text_selected, 6),
117 ribbon_unselected: color_definitions!(proto, ribbon_unselected, 6),
118 ribbon_selected: color_definitions!(proto, ribbon_selected, 6),
119 table_title: color_definitions!(proto, table_title, 6),
120 table_cell_unselected: color_definitions!(proto, table_cell_unselected, 6),
121 table_cell_selected: color_definitions!(proto, table_cell_selected, 6),
122 list_unselected: color_definitions!(proto, list_unselected, 6),
123 list_selected: color_definitions!(proto, list_selected, 6),
124 frame_unselected,
125 frame_selected: color_definitions!(proto, frame_selected, 6),
126 frame_highlight: color_definitions!(proto, frame_highlight, 6),
127 exit_code_success: color_definitions!(proto, exit_code_success, 6),
128 exit_code_error: color_definitions!(proto, exit_code_error, 6),
129 multiplayer_user_colors: multiplayer_colors!(proto, 10),
130 })
131 }
132}
133
134impl TryFrom<StyleDeclaration> for Vec<ProtobufColor> {
135 type Error = &'static str;
136
137 fn try_from(colors: StyleDeclaration) -> std::result::Result<Self, Self::Error> {
138 Ok(vec![
139 colors.base.try_into()?,
140 colors.background.try_into()?,
141 colors.emphasis_0.try_into()?,
142 colors.emphasis_1.try_into()?,
143 colors.emphasis_2.try_into()?,
144 colors.emphasis_3.try_into()?,
145 ])
146 }
147}
148
149impl TryFrom<MultiplayerColors> for Vec<ProtobufColor> {
150 type Error = &'static str;
151
152 fn try_from(value: MultiplayerColors) -> std::result::Result<Self, Self::Error> {
153 Ok(vec![
154 value.player_1.try_into()?,
155 value.player_2.try_into()?,
156 value.player_3.try_into()?,
157 value.player_4.try_into()?,
158 value.player_5.try_into()?,
159 value.player_6.try_into()?,
160 value.player_7.try_into()?,
161 value.player_8.try_into()?,
162 value.player_9.try_into()?,
163 value.player_10.try_into()?,
164 ])
165 }
166}
167
168impl TryFrom<Styling> for ProtobufStyling {
169 type Error = &'static str;
170
171 fn try_from(style: Styling) -> std::result::Result<Self, Self::Error> {
172 let frame_unselected_vec = match style.frame_unselected {
173 None => Ok(Vec::new()),
174 Some(frame_unselected) => frame_unselected.try_into(),
175 };
176
177 Ok(ProtobufStyling {
178 text_unselected: style.text_unselected.try_into()?,
179 text_selected: style.text_selected.try_into()?,
180 ribbon_unselected: style.ribbon_unselected.try_into()?,
181 ribbon_selected: style.ribbon_selected.try_into()?,
182 table_title: style.table_title.try_into()?,
183 table_cell_unselected: style.table_cell_unselected.try_into()?,
184 table_cell_selected: style.table_cell_selected.try_into()?,
185 list_unselected: style.list_unselected.try_into()?,
186 list_selected: style.list_selected.try_into()?,
187 frame_unselected: frame_unselected_vec?,
188 frame_selected: style.frame_selected.try_into()?,
189 frame_highlight: style.frame_highlight.try_into()?,
190 exit_code_success: style.exit_code_success.try_into()?,
191 exit_code_error: style.exit_code_error.try_into()?,
192 multiplayer_user_colors: style.multiplayer_user_colors.try_into()?,
193 })
194 }
195}
196
197impl TryFrom<ProtobufPalette> for Palette {
198 type Error = &'static str;
199 fn try_from(protobuf_palette: ProtobufPalette) -> Result<Self, &'static str> {
200 Ok(Palette {
201 theme_hue: ProtobufThemeHue::from_i32(protobuf_palette.theme_hue)
202 .ok_or("malformed theme_hue payload for Palette")?
203 .try_into()?,
204 fg: protobuf_palette
205 .fg
206 .ok_or("malformed palette payload")?
207 .try_into()?,
208 bg: protobuf_palette
209 .bg
210 .ok_or("malformed palette payload")?
211 .try_into()?,
212 black: protobuf_palette
213 .black
214 .ok_or("malformed palette payload")?
215 .try_into()?,
216 red: protobuf_palette
217 .red
218 .ok_or("malformed palette payload")?
219 .try_into()?,
220 green: protobuf_palette
221 .green
222 .ok_or("malformed palette payload")?
223 .try_into()?,
224 yellow: protobuf_palette
225 .yellow
226 .ok_or("malformed palette payload")?
227 .try_into()?,
228 blue: protobuf_palette
229 .blue
230 .ok_or("malformed palette payload")?
231 .try_into()?,
232 magenta: protobuf_palette
233 .magenta
234 .ok_or("malformed palette payload")?
235 .try_into()?,
236 cyan: protobuf_palette
237 .cyan
238 .ok_or("malformed palette payload")?
239 .try_into()?,
240 white: protobuf_palette
241 .white
242 .ok_or("malformed palette payload")?
243 .try_into()?,
244 orange: protobuf_palette
245 .orange
246 .ok_or("malformed palette payload")?
247 .try_into()?,
248 gray: protobuf_palette
249 .gray
250 .ok_or("malformed palette payload")?
251 .try_into()?,
252 purple: protobuf_palette
253 .purple
254 .ok_or("malformed palette payload")?
255 .try_into()?,
256 gold: protobuf_palette
257 .gold
258 .ok_or("malformed palette payload")?
259 .try_into()?,
260 silver: protobuf_palette
261 .silver
262 .ok_or("malformed palette payload")?
263 .try_into()?,
264 pink: protobuf_palette
265 .pink
266 .ok_or("malformed palette payload")?
267 .try_into()?,
268 brown: protobuf_palette
269 .brown
270 .ok_or("malformed palette payload")?
271 .try_into()?,
272 ..Default::default()
273 })
274 }
275}
276
277impl TryFrom<Palette> for ProtobufPalette {
278 type Error = &'static str;
279 fn try_from(palette: Palette) -> Result<Self, &'static str> {
280 let theme_hue: ProtobufThemeHue = palette
281 .theme_hue
282 .try_into()
283 .map_err(|_| "malformed payload for palette")?;
284 Ok(ProtobufPalette {
285 theme_hue: theme_hue as i32,
286 fg: Some(palette.fg.try_into()?),
287 bg: Some(palette.bg.try_into()?),
288 black: Some(palette.black.try_into()?),
289 red: Some(palette.red.try_into()?),
290 green: Some(palette.green.try_into()?),
291 yellow: Some(palette.yellow.try_into()?),
292 blue: Some(palette.blue.try_into()?),
293 magenta: Some(palette.magenta.try_into()?),
294 cyan: Some(palette.cyan.try_into()?),
295 white: Some(palette.white.try_into()?),
296 orange: Some(palette.orange.try_into()?),
297 gray: Some(palette.gray.try_into()?),
298 purple: Some(palette.purple.try_into()?),
299 gold: Some(palette.gold.try_into()?),
300 silver: Some(palette.silver.try_into()?),
301 pink: Some(palette.pink.try_into()?),
302 brown: Some(palette.brown.try_into()?),
303 ..Default::default()
304 })
305 }
306}
307
308impl TryFrom<ProtobufColor> for PaletteColor {
309 type Error = &'static str;
310 fn try_from(protobuf_color: ProtobufColor) -> Result<Self, &'static str> {
311 match ProtobufColorType::from_i32(protobuf_color.color_type) {
312 Some(ProtobufColorType::Rgb) => match protobuf_color.payload {
313 Some(ProtobufColorPayload::RgbColorPayload(rgb_color_payload)) => {
314 Ok(PaletteColor::Rgb((
315 rgb_color_payload.red as u8,
316 rgb_color_payload.green as u8,
317 rgb_color_payload.blue as u8,
318 )))
319 },
320 _ => Err("malformed payload for Rgb color"),
321 },
322 Some(ProtobufColorType::EightBit) => match protobuf_color.payload {
323 Some(ProtobufColorPayload::EightBitColorPayload(eight_bit_payload)) => {
324 Ok(PaletteColor::EightBit(eight_bit_payload as u8))
325 },
326 _ => Err("malformed payload for 8bit color"),
327 },
328 None => Err("malformed payload for Color"),
329 }
330 }
331}
332
333impl TryFrom<PaletteColor> for ProtobufColor {
334 type Error = &'static str;
335 fn try_from(color: PaletteColor) -> Result<Self, &'static str> {
336 match color {
337 PaletteColor::Rgb((red, green, blue)) => {
338 let red = red as u32;
339 let green = green as u32;
340 let blue = blue as u32;
341 Ok(ProtobufColor {
342 color_type: ProtobufColorType::Rgb as i32,
343 payload: Some(ProtobufColorPayload::RgbColorPayload(
344 ProtobufRgbColorPayload { red, green, blue },
345 )),
346 })
347 },
348 PaletteColor::EightBit(color) => Ok(ProtobufColor {
349 color_type: ProtobufColorType::EightBit as i32,
350 payload: Some(ProtobufColorPayload::EightBitColorPayload(color as u32)),
351 }),
352 }
353 }
354}
355
356impl TryFrom<ThemeHue> for ProtobufThemeHue {
357 type Error = &'static str;
358 fn try_from(theme_hue: ThemeHue) -> Result<Self, &'static str> {
359 match theme_hue {
360 ThemeHue::Light => Ok(ProtobufThemeHue::Light),
361 ThemeHue::Dark => Ok(ProtobufThemeHue::Dark),
362 }
363 }
364}
365
366impl TryFrom<ProtobufThemeHue> for ThemeHue {
367 type Error = &'static str;
368 fn try_from(protobuf_theme_hue: ProtobufThemeHue) -> Result<Self, &'static str> {
369 match protobuf_theme_hue {
370 ProtobufThemeHue::Light => Ok(ThemeHue::Light),
371 ProtobufThemeHue::Dark => Ok(ThemeHue::Dark),
372 }
373 }
374}