matchmaker/utils/
serde.rs

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