Skip to main content

logo_parser/
config.rs

1// SPDX-FileCopyrightText: 2023 CELESTIFYX Team
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use std::collections::HashMap;
5
6use serde::{
7    Deserialize,
8    Serialize
9};
10
11use chromakitx::AnyColor;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub(super) struct LogoEntry {
15    #[serde(rename = "type")]
16    pub(super) logo_type: String,
17    pub(super) ascii: Vec<String>
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21#[serde(untagged)]
22pub(super) enum ColorValue {
23    Reference(String),
24    Array(Vec<ColorDef>)
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(untagged)]
29pub(super) enum ColorDef {
30    Simple(String),
31    Named(HashMap<String, String>)
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub(super) struct LogoConfig {
36    pub(super) logos: Vec<LogoEntry>,
37    pub(super) colors: Vec<ColorValue>
38}
39
40impl LogoConfig {
41    pub(super) fn validate(&self) -> Result<(), String> {
42        if self.logos.is_empty() {
43            return Err("At least one logo is required".to_string());
44        }
45
46        let logo_type: String = self.logos[0].logo_type.to_lowercase();
47
48        if (logo_type != "large") && (logo_type != "small") {
49            return Err(format!("Logo type must be 'large' or 'small', found '{}'", self.logos[0].logo_type));
50        }
51
52        if self.colors.len() != 3 {
53            return Err(format!("Expected exactly 3 color elements, found {}", self.colors.len()));
54        }
55
56        if !matches!(&self.colors[0], ColorValue::Reference(_)) {
57            return Err("First color must be a reference string (e.g., '%0')".to_string());
58        }
59
60        if !matches!(&self.colors[1], ColorValue::Reference(_)) {
61            return Err("Second color must be a reference string (e.g., '%0')".to_string());
62        }
63
64        if !matches!(&self.colors[2], ColorValue::Array(_)) {
65            return Err("Third color element must be an array of color definitions".to_string());
66        }
67
68        Ok(())
69    }
70
71    pub(super) fn get_large_logo(&self) -> Option<Vec<String>> {
72        self.logos.iter().find(|l: &&LogoEntry| l.logo_type.to_lowercase() == "large").map(|l: &LogoEntry| l.ascii.clone())
73    }
74
75    pub(super) fn get_small_logo(&self) -> Option<Vec<String>> {
76        self.logos.iter().find(|l: &&LogoEntry| l.logo_type.to_lowercase() == "small").map(|l: &LogoEntry| l.ascii.clone())
77    }
78
79    pub(super) fn get_title_color_ref(&self) -> Option<String> {
80        if let ColorValue::Reference(s) = &self.colors[0] {
81            Some(s.clone())
82        } else {
83            None
84        }
85    }
86
87    pub(super) fn get_keys_color_ref(&self) -> Option<String> {
88        if let ColorValue::Reference(s) = &self.colors[1] {
89            Some(s.clone())
90        } else {
91            None
92        }
93    }
94
95    pub(super) fn get_color_defs(&self) -> Option<Vec<ColorDef>> {
96        if let ColorValue::Array(arr) = &self.colors[2] {
97            Some(arr.clone())
98        } else {
99            None
100        }
101    }
102}
103
104#[derive(Debug, Clone)]
105pub struct ColorConfig {
106    pub title_color: AnyColor,
107    pub keys_color: AnyColor,
108    pub ascii_colors: Vec<AnyColor>
109}