libsubconverter/settings/
yaml_deserializer.rs1use std::{collections::HashMap, fmt};
2
3use serde::{
4 de::{MapAccess, SeqAccess, Visitor},
5 Deserialize,
6};
7
8use super::settings::yaml_settings::TemplateSettings;
9
10#[derive(Debug, Clone, Deserialize, Default)]
12#[serde(default)]
13pub struct RegexMatchRuleInYaml {
14 #[serde(rename = "match")]
15 pub match_str: Option<String>,
16 pub replace: Option<String>,
17 pub script: Option<String>,
18 pub import: Option<String>,
19}
20
21pub trait ToIniWithDelimiter {
23 fn to_ini_with_delimiter(&self, delimiter: &str) -> String;
24}
25
26impl ToIniWithDelimiter for RegexMatchRuleInYaml {
27 fn to_ini_with_delimiter(&self, delimiter: &str) -> String {
28 if let Some(script) = &self.script {
30 if !script.is_empty() {
31 return format!("!!script:{}", script);
32 }
33 }
34
35 if let Some(import) = &self.import {
37 if !import.is_empty() {
38 return format!("!!import:{}", import);
39 }
40 }
41
42 if let (Some(match_str), Some(replace)) = (&self.match_str, &self.replace) {
44 if !match_str.is_empty() && !replace.is_empty() {
45 return format!("{}{}{}", match_str, delimiter, replace);
46 }
47 }
48
49 String::new()
51 }
52}
53
54pub trait ToIni {
55 fn to_ini(&self) -> String;
56}
57
58impl ToIni for RulesetConfigInYaml {
59 fn to_ini(&self) -> String {
60 if let Some(import) = &self.import {
62 if !import.is_empty() {
63 return format!("!!import:{}", import);
64 }
65 }
66
67 if let Some(ruleset) = &self.ruleset {
69 if !ruleset.is_empty() {
70 let mut result = format!("{},{}", self.group, ruleset);
71 if let Some(interval) = self.interval {
73 result = format!("{},{}", result, interval);
74 }
75 return result;
76 }
77 }
78
79 if let Some(rule) = &self.rule {
81 if !rule.is_empty() {
82 return format!("{},[]{}", self.group, rule);
83 }
84 }
85
86 String::new()
88 }
89}
90
91impl ToIni for TaskConfigInYaml {
92 fn to_ini(&self) -> String {
93 if let Some(import) = &self.import {
95 if !import.is_empty() {
96 return format!("!!import:{}", import);
97 }
98 }
99
100 format!(
102 "{}`{}`{}`{}",
103 self.name, self.cronexp, self.path, self.timeout
104 )
105 }
106}
107
108#[derive(Debug, Clone, Deserialize, Default)]
110#[serde(default)]
111pub struct ProxyGroupConfigInYaml {
112 pub name: String,
113 #[serde(rename = "type")]
114 pub group_type: String,
115 pub rule: Vec<String>,
116 #[serde(default = "default_test_url")]
117 pub url: Option<String>,
118 #[serde(default = "default_interval")]
119 pub interval: Option<u32>,
120 pub tolerance: Option<u32>,
121 pub timeout: Option<u32>,
122 pub import: Option<String>,
123}
124
125impl ToIni for ProxyGroupConfigInYaml {
126 fn to_ini(&self) -> String {
127 if let Some(import) = &self.import {
129 if !import.is_empty() {
130 return format!("!!import:{}", import);
131 }
132 }
133
134 let mut temp_array = vec![self.name.clone(), self.group_type.clone()];
136
137 for rule in &self.rule {
139 temp_array.push(rule.clone());
140 }
141
142 match self.group_type.as_str() {
144 "select" => {
145 if temp_array.len() < 3 {
146 return String::new();
147 }
148 }
149 "ssid" => {
150 if temp_array.len() < 4 {
151 return String::new();
152 }
153 }
154 _ => {
155 if temp_array.len() < 3 {
156 return String::new();
157 }
158
159 temp_array.push(
161 self.url
162 .clone()
163 .unwrap_or_else(|| "http://www.gstatic.com/generate_204".to_string()),
164 );
165
166 let interval = self.interval.unwrap_or(300).to_string();
168 let timeout = match self.timeout {
169 Some(t) => t.to_string(),
170 None => String::new(),
171 };
172 let tolerance = match self.tolerance {
173 Some(t) => t.to_string(),
174 None => String::new(),
175 };
176
177 temp_array.push(format!("{},{},{}", interval, timeout, tolerance));
178 }
179 }
180
181 temp_array.join("`")
183 }
184}
185
186fn default_test_url() -> Option<String> {
187 Some("http://www.gstatic.com/generate_204".to_string())
188}
189
190fn default_interval() -> Option<u32> {
191 Some(300)
192}
193
194#[derive(Debug, Clone, Deserialize, Default)]
196#[serde(default)]
197pub struct TaskConfigInYaml {
198 pub name: String,
199 pub cronexp: String,
200 pub path: String,
201 pub timeout: u32,
202 pub import: Option<String>,
203}
204
205#[derive(Debug, Clone, Deserialize, Default)]
207#[serde(default)]
208pub struct RulesetConfigInYaml {
209 pub rule: Option<String>,
210 pub ruleset: Option<String>,
211 pub group: String,
212 pub interval: Option<u32>,
213 pub import: Option<String>,
214}
215
216pub fn deserialize_template_as_template_settings<'de, D>(
217 deserializer: D,
218) -> Result<TemplateSettings, D::Error>
219where
220 D: serde::Deserializer<'de>,
221{
222 struct TemplateSettingsVisitor;
223
224 #[derive(Debug, Clone, Deserialize, Default)]
225 struct TemplateGlobalsVariable {
226 key: String,
227 #[serde(deserialize_with = "deserialize_as_string")]
228 value: String,
229 }
230
231 impl<'de> Visitor<'de> for TemplateSettingsVisitor {
232 type Value = TemplateSettings;
233
234 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
235 formatter.write_str("a TemplateSettings struct")
236 }
237
238 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
239 where
240 V: MapAccess<'de>,
241 {
242 let mut template_settings = TemplateSettings::default();
243 while let Some(key) = map.next_key::<String>()? {
244 if key == "template_path" {
245 let value = map.next_value::<String>()?;
246 template_settings.template_path = value.clone();
247 } else if key == "globals" {
248 let value = map.next_value::<Vec<TemplateGlobalsVariable>>()?;
249 for item in value {
250 template_settings.globals.insert(item.key, item.value);
251 }
252 }
253 }
254 Ok(template_settings)
255 }
256 }
257
258 deserializer.deserialize_any(TemplateSettingsVisitor)
259}
260
261#[derive(Debug, Clone, Deserialize, Default)]
263struct TemplateArgument {
264 pub key: String,
265 pub value: String,
266}
267
268pub fn deserialize_template_args_as_hash_map<'de, D>(
269 deserializer: D,
270) -> Result<Option<HashMap<String, String>>, D::Error>
271where
272 D: serde::Deserializer<'de>,
273{
274 struct TemplateArgsVisitor;
275
276 impl<'de> Visitor<'de> for TemplateArgsVisitor {
277 type Value = Option<HashMap<String, String>>;
278
279 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
280 formatter.write_str("a sequence of template arguments or null")
281 }
282
283 fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
284 where
285 S: SeqAccess<'de>,
286 {
287 let mut template_args = HashMap::new();
288
289 while let Some(item) = seq.next_element::<TemplateArgument>()? {
290 template_args.insert(item.key, item.value);
291 }
292
293 if template_args.is_empty() {
294 Ok(None)
295 } else {
296 Ok(Some(template_args))
297 }
298 }
299
300 fn visit_none<E>(self) -> Result<Self::Value, E>
301 where
302 E: serde::de::Error,
303 {
304 Ok(None)
305 }
306
307 fn visit_unit<E>(self) -> Result<Self::Value, E>
308 where
309 E: serde::de::Error,
310 {
311 Ok(None)
312 }
313
314 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
315 where
316 M: MapAccess<'de>,
317 {
318 let mut template_args = HashMap::new();
319
320 while let Some((key, value)) = map.next_entry::<String, String>()? {
321 template_args.insert(key, value);
322 }
323
324 if template_args.is_empty() {
325 Ok(None)
326 } else {
327 Ok(Some(template_args))
328 }
329 }
330 }
331
332 deserializer.deserialize_any(TemplateArgsVisitor)
333}
334
335pub fn deserialize_as_string<'de, D>(deserializer: D) -> Result<String, D::Error>
336where
337 D: serde::Deserializer<'de>,
338{
339 struct StringVisitor;
340
341 impl<'de> Visitor<'de> for StringVisitor {
342 type Value = String;
343
344 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
345 formatter.write_str("a string, number, or boolean")
346 }
347
348 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
349 where
350 E: serde::de::Error,
351 {
352 Ok(value.to_string())
353 }
354
355 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
356 where
357 E: serde::de::Error,
358 {
359 Ok(value)
360 }
361
362 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
363 where
364 E: serde::de::Error,
365 {
366 Ok(value.to_string())
367 }
368
369 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
370 where
371 E: serde::de::Error,
372 {
373 Ok(value.to_string())
374 }
375
376 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
377 where
378 E: serde::de::Error,
379 {
380 Ok(value.to_string())
381 }
382
383 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
384 where
385 E: serde::de::Error,
386 {
387 Ok(value.to_string())
388 }
389
390 fn visit_none<E>(self) -> Result<Self::Value, E>
391 where
392 E: serde::de::Error,
393 {
394 Ok(String::new())
395 }
396
397 fn visit_unit<E>(self) -> Result<Self::Value, E>
398 where
399 E: serde::de::Error,
400 {
401 Ok(String::new())
402 }
403 }
404
405 deserializer.deserialize_any(StringVisitor)
406}