1use super::{Color, DeviceSize, DeviceType};
2use serde::{de, ser};
3use serde_derive::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6use thiserror::Error;
7
8#[derive(Debug, Deserialize, Serialize)]
12pub struct RegistrationInfoDevice {
13 pub id: String,
15 pub name: Option<String>,
19 pub size: DeviceSize,
21 #[serde(rename = "type")]
23 pub _type: Option<DeviceType>,
24}
25
26#[derive(Debug)]
30pub enum Language {
31 English,
32 French,
33 German,
34 Spanish,
35 Japanese,
36 Korean,
37 ChineseChina,
39 ChineseTaiwan,
41 Unknown(String),
43}
44
45impl<'de> de::Deserialize<'de> for Language {
46 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47 where
48 D: de::Deserializer<'de>,
49 {
50 struct Visitor;
51
52 impl<'de> de::Visitor<'de> for Visitor {
53 type Value = Language;
54
55 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
56 formatter.write_str("a string")
57 }
58
59 fn visit_str<E>(self, value: &str) -> Result<Language, E>
60 where
61 E: de::Error,
62 {
63 Ok(match value {
64 "en" => Language::English,
65 "fr" => Language::French,
66 "de" => Language::German,
67 "es" => Language::Spanish,
68 "ja" => Language::Japanese,
69 "zh_cn" => Language::ChineseChina,
71 "ko" => Language::Korean,
73 "zh_CN" => Language::ChineseChina,
74 "zh_TW" => Language::ChineseTaiwan,
75 value => Language::Unknown(value.to_string()),
76 })
77 }
78 }
79
80 deserializer.deserialize_str(Visitor)
81 }
82}
83
84impl ser::Serialize for Language {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: ser::Serializer,
88 {
89 let lang = match self {
90 Language::English => "en",
91 Language::French => "fr",
92 Language::German => "de",
93 Language::Spanish => "es",
94 Language::Japanese => "ja",
95 Language::Korean => "ko",
96 Language::ChineseChina => "zh_CN",
97 Language::ChineseTaiwan => "zh_TW",
98 Language::Unknown(value) => value,
99 };
100
101 serializer.serialize_str(lang)
102 }
103}
104
105#[derive(Debug)]
107pub enum Platform {
108 Mac,
110 Windows,
112 Unknown(String),
114}
115
116impl ser::Serialize for Platform {
117 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: ser::Serializer,
120 {
121 let platform = match self {
122 Platform::Mac => "mac",
123 Platform::Windows => "windows",
124 Platform::Unknown(s) => s,
125 };
126
127 serializer.serialize_str(platform)
128 }
129}
130
131impl<'de> de::Deserialize<'de> for Platform {
132 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
133 where
134 D: de::Deserializer<'de>,
135 {
136 struct Visitor;
137
138 impl<'de> de::Visitor<'de> for Visitor {
139 type Value = Platform;
140
141 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
142 formatter.write_str("a string")
143 }
144
145 fn visit_str<E>(self, value: &str) -> Result<Platform, E>
146 where
147 E: de::Error,
148 {
149 Ok(match value {
150 "mac" => Platform::Mac,
151 "windows" => Platform::Windows,
152 value => Platform::Unknown(value.to_string()),
153 })
154 }
155 }
156
157 deserializer.deserialize_str(Visitor)
158 }
159}
160
161#[derive(Debug, Deserialize, Serialize)]
165pub struct RegistrationInfoApplication {
166 pub font: String,
168 pub language: Language,
170 pub platform: Platform,
172 #[serde(rename = "platformVersion")]
174 pub platform_version: String,
175 pub version: String,
177}
178
179#[derive(Serialize, Deserialize, Debug, Clone)]
183#[serde(rename_all = "camelCase")]
184pub struct RegistrationInfoPlugin {
185 pub version: String,
187 pub uuid: String,
189}
190
191#[derive(Clone, Deserialize, Serialize, Debug, Default)]
195#[serde(rename_all = "camelCase")]
196pub struct UserColors {
197 pub button_mouse_over_background_color: Option<Color>,
199 pub button_pressed_background_color: Option<Color>,
201 pub button_pressed_border_color: Option<Color>,
203 pub button_pressed_text_color: Option<Color>,
205 pub highlight_color: Option<Color>,
207}
208
209#[derive(Debug, Deserialize, Serialize)]
213#[serde(rename_all = "camelCase")]
214pub struct RegistrationInfo {
215 pub application: RegistrationInfoApplication,
216 pub plugin: RegistrationInfoPlugin,
217 pub device_pixel_ratio: f64,
218 pub devices: Vec<RegistrationInfoDevice>,
219 pub colors: UserColors,
220}
221
222#[derive(Deserialize)]
226pub struct RegistrationParams {
227 pub port: u16,
229 pub uuid: String,
231 pub event: String,
233 pub info: RegistrationInfo,
235}
236
237#[derive(Debug, Error)]
239pub enum RegistrationParamsError {
240 #[error("port not provided")]
242 NoPort,
243 #[error("port could not be parsed")]
245 BadPort(#[source] std::num::ParseIntError),
246 #[error("uuid not provided")]
248 NoUuid,
249 #[error("event not provided")]
251 NoEvent,
252 #[error("info not provided")]
254 NoInfo,
255 #[error("info could not be parsed")]
257 BadInfo(#[from] serde_json::Error),
258}
259
260impl RegistrationParams {
261 pub fn from_args<I: IntoIterator<Item = String>>(
269 args: I,
270 ) -> Result<RegistrationParams, RegistrationParamsError> {
271 let mut iter = args.into_iter();
272 let mut port = None;
273 let mut uuid = None;
274 let mut event = None;
275 let mut info = None;
276
277 loop {
278 match iter.next().as_deref() {
279 Some("-port") => port = iter.next().map(|a| u16::from_str(&a)),
280 Some("-pluginUUID") => uuid = iter.next(),
281 Some("-registerEvent") => event = iter.next(),
282 Some("-info") => info = iter.next().map(|a| serde_json::from_str(&a)),
283 Some(_) => {}
284 None => break,
285 }
286 }
287 let port = port
288 .ok_or(RegistrationParamsError::NoPort)?
289 .map_err(RegistrationParamsError::BadPort)?;
290 let uuid = uuid.ok_or(RegistrationParamsError::NoUuid)?;
291 let event = event.ok_or(RegistrationParamsError::NoEvent)?;
292 let info = info
293 .ok_or(RegistrationParamsError::NoInfo)?
294 .map_err(RegistrationParamsError::BadInfo)?;
295
296 Ok(RegistrationParams {
297 port,
298 uuid,
299 event,
300 info,
301 })
302 }
303}