matchmaker/utils/
serde.rs

1#![allow(unused)]
2use cli_boilerplate_automation::wbog;
3use serde::{Deserialize, Deserializer, Serialize, de};
4
5use crate::utils::text::parse_escapes;
6
7pub mod fromstr {
8    use serde::{Deserialize, Deserializer, Serializer, de};
9    use std::fmt::Display;
10    use std::str::FromStr;
11
12    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
13    where
14        T: Display,
15        S: Serializer,
16    {
17        serializer.serialize_str(&value.to_string())
18    }
19
20    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
21    where
22        T: FromStr,
23        T::Err: Display,
24        D: Deserializer<'de>,
25    {
26        let s = String::deserialize(deserializer)?;
27        T::from_str(&s).map_err(de::Error::custom)
28    }
29}
30
31#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32#[serde(untagged)]
33pub enum StringOrVec {
34    String(String),
35    Vec(Vec<String>),
36}
37impl Default for StringOrVec {
38    fn default() -> Self {
39        StringOrVec::String(String::new())
40    }
41}
42
43pub fn bounded_usize<'de, const MAX: usize, D>(d: D) -> Result<usize, D::Error>
44where
45    D: Deserializer<'de>,
46{
47    let v = usize::deserialize(d)?;
48    if v > MAX {
49        wbog!("{} exceeded the the limit of {} and was clamped.", v, MAX);
50        Ok(MAX)
51    } else {
52        Ok(v)
53        // return Err(serde::de::Error::custom(format!"{} exceeds the maximum of {MAX}"));
54    }
55}
56
57pub fn escaped_opt_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
58where
59    D: serde::Deserializer<'de>,
60{
61    let opt = Option::<String>::deserialize(deserializer)?;
62    Ok(opt.map(|s| parse_escapes(&s)))
63}
64
65pub fn escaped_opt_char<'de, D>(deserializer: D) -> Result<Option<char>, D::Error>
66where
67    D: serde::Deserializer<'de>,
68{
69    let opt = Option::<String>::deserialize(deserializer)?;
70    match opt {
71        Some(s) => {
72            let parsed = parse_escapes(&s);
73            let mut chars = parsed.chars();
74            let first = chars
75                .next()
76                .ok_or_else(|| serde::de::Error::custom("escaped string is empty"))?;
77            if chars.next().is_some() {
78                return Err(serde::de::Error::custom(
79                    "escaped string must be exactly one character",
80                ));
81            }
82            Ok(Some(first))
83        }
84        None => Ok(None),
85    }
86}
87
88pub mod serde_duration_ms {
89    use serde::{Deserialize, Deserializer, Serializer};
90    use std::time::Duration;
91
92    pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
93    where
94        S: Serializer,
95    {
96        let ms = duration.as_millis() as u64;
97        serializer.serialize_u64(ms)
98    }
99
100    pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
101    where
102        D: Deserializer<'de>,
103    {
104        let ms = u64::deserialize(deserializer)?;
105        Ok(Duration::from_millis(ms))
106    }
107}