1use crate::input::{GamepadAction, GenericInput, KeyboardInput};
2use sdl3::mouse::MouseButton;
3use serde::de::{Error, Visitor};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use std::fmt::Formatter;
6use std::str::FromStr;
7
8impl Serialize for KeyboardInput {
9    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
10    where
11        S: Serializer,
12    {
13        serializer.serialize_str(&self.serialize_to_str())
14    }
15}
16
17impl<'de> Deserialize<'de> for KeyboardInput {
18    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
19    where
20        D: Deserializer<'de>,
21    {
22        struct KeyboardInputVisitor;
23
24        impl Visitor<'_> for KeyboardInputVisitor {
25            type Value = KeyboardInput;
26
27            fn expecting(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
28                write!(formatter, "KeyboardInput")
29            }
30
31            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
32            where
33                E: Error,
34            {
35                let key = KeyboardInput::deserialize_from_str(v).ok_or_else(|| {
36                    Error::custom(format!("Invalid keyboard input string: '{v}'"))
37                })?;
38                Ok(key)
39            }
40        }
41
42        deserializer.deserialize_str(KeyboardInputVisitor)
43    }
44}
45
46// Serialize GamepadAction as a single string to avoid making the TOML config extremely messy
47struct SerializableGamepadAction(GamepadAction);
48
49impl Serialize for SerializableGamepadAction {
50    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
51    where
52        S: Serializer,
53    {
54        serializer.serialize_str(&self.0.to_string())
55    }
56}
57
58impl<'de> Deserialize<'de> for SerializableGamepadAction {
59    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60    where
61        D: Deserializer<'de>,
62    {
63        struct GamepadActionVisitor;
64
65        impl Visitor<'_> for GamepadActionVisitor {
66            type Value = SerializableGamepadAction;
67
68            fn expecting(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
69                write!(formatter, "SerializableGamepadAction")
70            }
71
72            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
73            where
74                E: Error,
75            {
76                Ok(SerializableGamepadAction(
77                    GamepadAction::from_str(v).map_err(|_| {
78                        Error::custom(format!("Invalid gamepad action string: '{v}'"))
79                    })?,
80                ))
81            }
82        }
83
84        deserializer.deserialize_str(GamepadActionVisitor)
85    }
86}
87
88// Only exists because MouseButton does not implement serde traits
89#[derive(Serialize, Deserialize)]
90enum SerializableMouseButton {
91    Unknown,
92    Left,
93    Right,
94    Middle,
95    X1,
96    X2,
97}
98
99macro_rules! impl_from_mouse_button {
100    ($a:ty, $b:ty) => {
101        impl From<$a> for $b {
102            fn from(value: $a) -> Self {
103                match value {
104                    <$a>::Unknown => Self::Unknown,
105                    <$a>::Left => Self::Left,
106                    <$a>::Right => Self::Right,
107                    <$a>::Middle => Self::Middle,
108                    <$a>::X1 => Self::X1,
109                    <$a>::X2 => Self::X2,
110                }
111            }
112        }
113    };
114}
115
116impl_from_mouse_button!(MouseButton, SerializableMouseButton);
117impl_from_mouse_button!(SerializableMouseButton, MouseButton);
118
119// Alternate representation of GenericInput that serializes in a nicer format
120#[derive(Serialize, Deserialize)]
121#[serde(tag = "type")]
122enum SerializableGenericInput {
123    Keyboard { key: KeyboardInput },
124    Gamepad { gamepad_idx: u32, action: SerializableGamepadAction },
125    Mouse { button: SerializableMouseButton },
126}
127
128impl Serialize for GenericInput {
129    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
130    where
131        S: Serializer,
132    {
133        let serializable = match *self {
134            Self::Keyboard(key) => SerializableGenericInput::Keyboard { key },
135            Self::Gamepad { gamepad_idx, action } => SerializableGenericInput::Gamepad {
136                gamepad_idx,
137                action: SerializableGamepadAction(action),
138            },
139            Self::Mouse(button) => SerializableGenericInput::Mouse { button: button.into() },
140        };
141
142        serializable.serialize(serializer)
143    }
144}
145
146impl<'de> Deserialize<'de> for GenericInput {
147    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148    where
149        D: Deserializer<'de>,
150    {
151        let serializable = SerializableGenericInput::deserialize(deserializer)?;
152
153        Ok(match serializable {
154            SerializableGenericInput::Keyboard { key } => Self::Keyboard(key),
155            SerializableGenericInput::Gamepad { gamepad_idx, action } => {
156                Self::Gamepad { gamepad_idx, action: action.0 }
157            }
158            SerializableGenericInput::Mouse { button } => Self::Mouse(button.into()),
159        })
160    }
161}