Skip to main content

zellij_utils/plugin_api/
style.rs

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}