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::try_from(protobuf_palette.theme_hue)
202 .ok()
203 .ok_or("malformed theme_hue payload for Palette")?
204 .try_into()?,
205 fg: protobuf_palette
206 .fg
207 .ok_or("malformed palette payload")?
208 .try_into()?,
209 bg: protobuf_palette
210 .bg
211 .ok_or("malformed palette payload")?
212 .try_into()?,
213 black: protobuf_palette
214 .black
215 .ok_or("malformed palette payload")?
216 .try_into()?,
217 red: protobuf_palette
218 .red
219 .ok_or("malformed palette payload")?
220 .try_into()?,
221 green: protobuf_palette
222 .green
223 .ok_or("malformed palette payload")?
224 .try_into()?,
225 yellow: protobuf_palette
226 .yellow
227 .ok_or("malformed palette payload")?
228 .try_into()?,
229 blue: protobuf_palette
230 .blue
231 .ok_or("malformed palette payload")?
232 .try_into()?,
233 magenta: protobuf_palette
234 .magenta
235 .ok_or("malformed palette payload")?
236 .try_into()?,
237 cyan: protobuf_palette
238 .cyan
239 .ok_or("malformed palette payload")?
240 .try_into()?,
241 white: protobuf_palette
242 .white
243 .ok_or("malformed palette payload")?
244 .try_into()?,
245 orange: protobuf_palette
246 .orange
247 .ok_or("malformed palette payload")?
248 .try_into()?,
249 gray: protobuf_palette
250 .gray
251 .ok_or("malformed palette payload")?
252 .try_into()?,
253 purple: protobuf_palette
254 .purple
255 .ok_or("malformed palette payload")?
256 .try_into()?,
257 gold: protobuf_palette
258 .gold
259 .ok_or("malformed palette payload")?
260 .try_into()?,
261 silver: protobuf_palette
262 .silver
263 .ok_or("malformed palette payload")?
264 .try_into()?,
265 pink: protobuf_palette
266 .pink
267 .ok_or("malformed palette payload")?
268 .try_into()?,
269 brown: protobuf_palette
270 .brown
271 .ok_or("malformed palette payload")?
272 .try_into()?,
273 ..Default::default()
274 })
275 }
276}
277
278impl TryFrom<Palette> for ProtobufPalette {
279 type Error = &'static str;
280 fn try_from(palette: Palette) -> Result<Self, &'static str> {
281 let theme_hue: ProtobufThemeHue = palette
282 .theme_hue
283 .try_into()
284 .map_err(|_| "malformed payload for palette")?;
285 Ok(ProtobufPalette {
286 theme_hue: theme_hue as i32,
287 fg: Some(palette.fg.try_into()?),
288 bg: Some(palette.bg.try_into()?),
289 black: Some(palette.black.try_into()?),
290 red: Some(palette.red.try_into()?),
291 green: Some(palette.green.try_into()?),
292 yellow: Some(palette.yellow.try_into()?),
293 blue: Some(palette.blue.try_into()?),
294 magenta: Some(palette.magenta.try_into()?),
295 cyan: Some(palette.cyan.try_into()?),
296 white: Some(palette.white.try_into()?),
297 orange: Some(palette.orange.try_into()?),
298 gray: Some(palette.gray.try_into()?),
299 purple: Some(palette.purple.try_into()?),
300 gold: Some(palette.gold.try_into()?),
301 silver: Some(palette.silver.try_into()?),
302 pink: Some(palette.pink.try_into()?),
303 brown: Some(palette.brown.try_into()?),
304 ..Default::default()
305 })
306 }
307}
308
309impl TryFrom<ProtobufColor> for PaletteColor {
310 type Error = &'static str;
311 fn try_from(protobuf_color: ProtobufColor) -> Result<Self, &'static str> {
312 match ProtobufColorType::try_from(protobuf_color.color_type).ok() {
313 Some(ProtobufColorType::Rgb) => match protobuf_color.payload {
314 Some(ProtobufColorPayload::RgbColorPayload(rgb_color_payload)) => {
315 Ok(PaletteColor::Rgb((
316 rgb_color_payload.red as u8,
317 rgb_color_payload.green as u8,
318 rgb_color_payload.blue as u8,
319 )))
320 },
321 _ => Err("malformed payload for Rgb color"),
322 },
323 Some(ProtobufColorType::EightBit) => match protobuf_color.payload {
324 Some(ProtobufColorPayload::EightBitColorPayload(eight_bit_payload)) => {
325 Ok(PaletteColor::EightBit(eight_bit_payload as u8))
326 },
327 _ => Err("malformed payload for 8bit color"),
328 },
329 None => Err("malformed payload for Color"),
330 }
331 }
332}
333
334impl TryFrom<PaletteColor> for ProtobufColor {
335 type Error = &'static str;
336 fn try_from(color: PaletteColor) -> Result<Self, &'static str> {
337 match color {
338 PaletteColor::Rgb((red, green, blue)) => {
339 let red = red as u32;
340 let green = green as u32;
341 let blue = blue as u32;
342 Ok(ProtobufColor {
343 color_type: ProtobufColorType::Rgb as i32,
344 payload: Some(ProtobufColorPayload::RgbColorPayload(
345 ProtobufRgbColorPayload { red, green, blue },
346 )),
347 })
348 },
349 PaletteColor::EightBit(color) => Ok(ProtobufColor {
350 color_type: ProtobufColorType::EightBit as i32,
351 payload: Some(ProtobufColorPayload::EightBitColorPayload(color as u32)),
352 }),
353 }
354 }
355}
356
357impl TryFrom<ThemeHue> for ProtobufThemeHue {
358 type Error = &'static str;
359 fn try_from(theme_hue: ThemeHue) -> Result<Self, &'static str> {
360 match theme_hue {
361 ThemeHue::Light => Ok(ProtobufThemeHue::Light),
362 ThemeHue::Dark => Ok(ProtobufThemeHue::Dark),
363 }
364 }
365}
366
367impl TryFrom<ProtobufThemeHue> for ThemeHue {
368 type Error = &'static str;
369 fn try_from(protobuf_theme_hue: ProtobufThemeHue) -> Result<Self, &'static str> {
370 match protobuf_theme_hue {
371 ProtobufThemeHue::Light => Ok(ThemeHue::Light),
372 ProtobufThemeHue::Dark => Ok(ThemeHue::Dark),
373 }
374 }
375}