hex_patch/app/settings/
settings_value.rs

1use std::fmt::{Display, Formatter};
2
3use crossterm::event::{KeyCode, KeyEvent, KeyEventState, KeyModifiers};
4use mlua::{FromLua, IntoLua};
5use ratatui::style::{Modifier, Style};
6use serde::{ser::SerializeMap, Deserialize, Serialize};
7
8use super::{
9    key_settings::KeySettings,
10    register_color_settings_macro::{get_style, set_style},
11    register_key_settings_macro::{key_event_to_lua, lua_to_key_event},
12};
13
14#[derive(Debug, Clone, PartialEq)]
15pub enum SettingsValue {
16    Bool(bool),
17    Int(i64),
18    Float(f64),
19    String(String),
20    Style(Style),
21    Key(KeyEvent),
22}
23
24impl From<bool> for SettingsValue {
25    fn from(value: bool) -> Self {
26        SettingsValue::Bool(value)
27    }
28}
29
30impl From<i64> for SettingsValue {
31    fn from(value: i64) -> Self {
32        SettingsValue::Int(value)
33    }
34}
35
36impl From<f64> for SettingsValue {
37    fn from(value: f64) -> Self {
38        SettingsValue::Float(value)
39    }
40}
41
42impl From<String> for SettingsValue {
43    fn from(value: String) -> Self {
44        SettingsValue::String(value)
45    }
46}
47
48impl From<&str> for SettingsValue {
49    fn from(value: &str) -> Self {
50        SettingsValue::String(value.to_string())
51    }
52}
53
54impl From<Style> for SettingsValue {
55    fn from(value: Style) -> Self {
56        SettingsValue::Style(value)
57    }
58}
59
60impl From<KeyEvent> for SettingsValue {
61    fn from(value: KeyEvent) -> Self {
62        SettingsValue::Key(value)
63    }
64}
65
66impl Display for SettingsValue {
67    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68        match self {
69            SettingsValue::Bool(value) => write!(f, "{value}"),
70            SettingsValue::Int(value) => write!(f, "{value}"),
71            SettingsValue::Float(value) => write!(f, "{value}"),
72            SettingsValue::String(value) => write!(f, "{value}"),
73            SettingsValue::Style(value) => {
74                write!(
75                    f,
76                    "{{fg:{},",
77                    value.fg.map_or("None".to_string(), |c| c.to_string())
78                )?;
79                write!(
80                    f,
81                    "bg:{},",
82                    value.bg.map_or("None".to_string(), |c| c.to_string())
83                )?;
84                write!(
85                    f,
86                    "underline:{},",
87                    value
88                        .underline_color
89                        .map_or("None".to_string(), |c| c.to_string())
90                )?;
91                write!(f, "add_modifier:{},", value.add_modifier.bits())?;
92                write!(f, "sub_modifier:{}}}", value.sub_modifier.bits())?;
93                Ok(())
94            }
95            SettingsValue::Key(value) => {
96                write!(f, "{{code:{},", KeySettings::key_code_to_string(value.code))?;
97                write!(f, "modifiers:{},", value.modifiers.bits())?;
98                write!(
99                    f,
100                    "kind:{},",
101                    KeySettings::key_event_kind_to_string(value.kind)
102                )?;
103                write!(f, "state:{}}}", value.state.bits())?;
104                Ok(())
105            }
106        }
107    }
108}
109
110impl Serialize for SettingsValue {
111    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112    where
113        S: serde::Serializer,
114    {
115        match self {
116            SettingsValue::Bool(value) => serializer.serialize_bool(*value),
117            SettingsValue::Int(value) => serializer.serialize_i64(*value),
118            SettingsValue::Float(value) => serializer.serialize_f64(*value),
119            SettingsValue::String(value) => serializer.serialize_str(value),
120            SettingsValue::Style(value) => {
121                let len = 2
122                    + value.fg.is_some() as usize
123                    + value.bg.is_some() as usize
124                    + value.underline_color.is_some() as usize;
125                let mut map = serializer.serialize_map(Some(len))?;
126                if let Some(fg) = value.fg {
127                    map.serialize_key("fg")?;
128                    map.serialize_value(&fg.to_string())?;
129                }
130                if let Some(bg) = value.bg {
131                    map.serialize_key("bg")?;
132                    map.serialize_value(&bg.to_string())?;
133                }
134                if let Some(underline) = value.underline_color {
135                    map.serialize_key("underline")?;
136                    map.serialize_value(&underline.to_string())?;
137                }
138                map.serialize_key("add_modifier")?;
139                map.serialize_value(&value.add_modifier.bits())?;
140                map.serialize_key("sub_modifier")?;
141                map.serialize_value(&value.sub_modifier.bits())?;
142                map.end()
143            }
144            SettingsValue::Key(value) => {
145                let mut map = serializer.serialize_map(Some(4))?;
146                map.serialize_key("code")?;
147                map.serialize_value(&KeySettings::key_code_to_string(value.code))?;
148                map.serialize_key("modifiers")?;
149                map.serialize_value(&value.modifiers.bits())?;
150                map.serialize_key("kind")?;
151                map.serialize_value(&KeySettings::key_event_kind_to_string(value.kind))?;
152                map.serialize_key("state")?;
153                map.serialize_value(&value.state.bits())?;
154                map.end()
155            }
156        }
157    }
158}
159
160struct SettingsValueVisitor;
161
162impl SettingsValueVisitor {
163    fn visit_bool<E>(self, value: bool) -> Result<SettingsValue, E> {
164        Ok(SettingsValue::Bool(value))
165    }
166
167    fn visit_i64<E>(self, value: i64) -> Result<SettingsValue, E> {
168        Ok(SettingsValue::Int(value))
169    }
170
171    fn visit_f64<E>(self, value: f64) -> Result<SettingsValue, E> {
172        Ok(SettingsValue::Float(value))
173    }
174
175    fn visit_str<E>(self, value: &str) -> Result<SettingsValue, E> {
176        Ok(SettingsValue::String(value.to_string()))
177    }
178
179    fn visit_style<E>(self, style: Style) -> Result<SettingsValue, E> {
180        Ok(SettingsValue::Style(style))
181    }
182
183    fn visit_key<E>(self, value: KeyEvent) -> Result<SettingsValue, E> {
184        Ok(SettingsValue::Key(value))
185    }
186}
187
188impl<'de> serde::de::Visitor<'de> for SettingsValueVisitor {
189    type Value = SettingsValue;
190
191    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
192        formatter.write_str("a boolean, integer, number, string, style, or key event")
193    }
194
195    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
196        self.visit_bool(value)
197    }
198
199    fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
200    where
201        E: serde::de::Error,
202    {
203        self.visit_i64(v.into())
204    }
205
206    fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
207    where
208        E: serde::de::Error,
209    {
210        self.visit_i64(v.into())
211    }
212
213    fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
214    where
215        E: serde::de::Error,
216    {
217        self.visit_i64(v.into())
218    }
219
220    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
221        self.visit_i64(value)
222    }
223
224    fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
225    where
226        E: serde::de::Error,
227    {
228        self.visit_i64(v.into())
229    }
230
231    fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
232    where
233        E: serde::de::Error,
234    {
235        self.visit_i64(v.into())
236    }
237
238    fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
239    where
240        E: serde::de::Error,
241    {
242        self.visit_i64(v.into())
243    }
244
245    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
246    where
247        E: serde::de::Error,
248    {
249        if let Ok(value) = i64::try_from(v) {
250            self.visit_i64(value)
251        } else {
252            Err(E::custom(t!("errors.u64_too_large_for_i64")))
253        }
254    }
255
256    fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
257    where
258        E: serde::de::Error,
259    {
260        self.visit_f64(v.into())
261    }
262
263    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
264        self.visit_f64(value)
265    }
266
267    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> {
268        self.visit_str(value)
269    }
270
271    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
272    where
273        A: serde::de::MapAccess<'de>,
274    {
275        let mut style = Style::default();
276        let mut key_event = KeyEvent::new(KeyCode::Null, KeyModifiers::NONE);
277        #[derive(Debug, PartialEq)]
278        enum MapKind {
279            Unknown,
280            Style,
281            Key,
282        }
283        let mut map_kind = MapKind::Unknown;
284        while let Some(key) = map.next_key()? {
285            if map_kind == MapKind::Unknown {
286                match key {
287                    "fg" | "bg" | "underline" | "add_modifier" | "sub_modifier" => {
288                        map_kind = MapKind::Style;
289                    }
290                    "code" | "modifiers" | "kind" | "state" => {
291                        map_kind = MapKind::Key;
292                    }
293                    _ => break,
294                }
295            }
296
297            match map_kind {
298                MapKind::Unknown => break,
299                MapKind::Style => match key {
300                    "fg" => {
301                        let value = map.next_value()?;
302                        style.fg = Some(value);
303                    }
304                    "bg" => {
305                        let value = map.next_value()?;
306                        style.bg = Some(value);
307                    }
308                    "underline" => {
309                        let value = map.next_value()?;
310                        style.underline_color = Some(value);
311                    }
312                    "add_modifier" => {
313                        let value = map.next_value()?;
314                        style.add_modifier = Modifier::from_bits(value).ok_or_else(|| {
315                            serde::de::Error::custom(t!("errors.invalid_style_add_modifier"))
316                        })?;
317                    }
318                    "sub_modifier" => {
319                        let value = map.next_value()?;
320                        style.sub_modifier = Modifier::from_bits(value).ok_or_else(|| {
321                            serde::de::Error::custom(t!("errors.invalid_style_sub_modifier"))
322                        })?;
323                    }
324                    _ => {
325                        map_kind = MapKind::Unknown;
326                        break;
327                    }
328                },
329                MapKind::Key => match key {
330                    "code" => {
331                        let value = map.next_value::<String>()?;
332                        key_event.code = KeySettings::string_to_key_code(&value)
333                            .map_err(serde::de::Error::custom)?;
334                    }
335                    "modifiers" => {
336                        let value = map.next_value()?;
337                        key_event.modifiers = KeyModifiers::from_bits(value).ok_or_else(|| {
338                            serde::de::Error::custom(t!("errors.invalid_key_modifiers"))
339                        })?;
340                    }
341                    "kind" => {
342                        let value = map.next_value::<String>()?;
343                        key_event.kind = KeySettings::string_to_key_event_kind(&value)
344                            .map_err(serde::de::Error::custom)?;
345                    }
346                    "state" => {
347                        let value = map.next_value()?;
348                        key_event.state = KeyEventState::from_bits(value).ok_or_else(|| {
349                            serde::de::Error::custom(t!("errors.invalid_key_event_state"))
350                        })?;
351                    }
352                    _ => {
353                        map_kind = MapKind::Unknown;
354                        break;
355                    }
356                },
357            }
358        }
359        match map_kind {
360            MapKind::Unknown => Err(serde::de::Error::custom(t!(
361                "errors.invalid_table_style_or_key_event"
362            ))),
363            MapKind::Style => self.visit_style(style),
364            MapKind::Key => self.visit_key(key_event),
365        }
366    }
367}
368
369impl<'de> Deserialize<'de> for SettingsValue {
370    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
371    where
372        D: serde::Deserializer<'de>,
373    {
374        deserializer.deserialize_any(SettingsValueVisitor)
375    }
376}
377
378impl IntoLua for SettingsValue {
379    fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
380        match self {
381            SettingsValue::Bool(value) => value.into_lua(lua),
382            SettingsValue::Int(value) => value.into_lua(lua),
383            SettingsValue::Float(value) => value.into_lua(lua),
384            SettingsValue::String(value) => value.into_lua(lua),
385            SettingsValue::Style(value) => Ok(mlua::Value::Table(get_style(lua, &value)?)),
386            SettingsValue::Key(value) => Ok(mlua::Value::Table(key_event_to_lua(lua, &value)?)),
387        }
388    }
389}
390
391impl FromLua for SettingsValue {
392    fn from_lua(value: mlua::Value, _lua: &mlua::Lua) -> mlua::Result<Self> {
393        match value {
394            mlua::Value::Boolean(value) => Ok(SettingsValue::Bool(value)),
395            mlua::Value::Integer(value) => Ok(SettingsValue::Int(value)),
396            mlua::Value::Number(value) => Ok(SettingsValue::Float(value)),
397            mlua::Value::String(value) => Ok(SettingsValue::String(value.to_str()?.to_string())),
398            mlua::Value::Table(value) => {
399                if value.contains_key("fg")?
400                    || value.contains_key("bg")?
401                    || value.contains_key("underline")?
402                    || value.contains_key("add_modifier")?
403                    || value.contains_key("sub_modifier")?
404                {
405                    let mut style = Style::default();
406                    set_style(_lua, &mut style, value)?;
407                    Ok(SettingsValue::Style(style))
408                } else if value.contains_key("code")?
409                    || value.contains_key("modifiers")?
410                    || value.contains_key("kind")?
411                    || value.contains_key("state")?
412                {
413                    let key_event = lua_to_key_event(_lua, &value)?;
414                    Ok(SettingsValue::Key(key_event))
415                } else {
416                    Err(mlua::Error::RuntimeError(
417                        "Invalid table, expected style or key event".to_string(),
418                    ))
419                }
420            }
421            _ => Err(mlua::Error::RuntimeError(
422                "Expected boolean, integer, number, string, style or key event".to_string(),
423            )),
424        }
425    }
426}