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::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}