shared/
deserialize.rs

1use indexmap::IndexMap;
2use serde::{Deserialize, Deserializer, de::DeserializeOwned};
3
4#[inline]
5pub fn deserialize_defaultable<'de, T, D>(deserializer: D) -> Result<T, D::Error>
6where
7    T: DeserializeOwned + Default,
8    D: Deserializer<'de>,
9{
10    let value = serde_json::Value::deserialize(deserializer)?;
11
12    Ok(serde_json::from_value(value).unwrap_or_default())
13}
14
15pub fn deserialize_stringable_option<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
16where
17    D: Deserializer<'de>,
18{
19    let value = serde_json::Value::deserialize(deserializer).unwrap_or_default();
20    Ok(match value {
21        serde_json::Value::Null => None,
22        serde_json::Value::String(string) if string.is_empty() => None,
23        serde_json::Value::String(string) => Some(string),
24        value => Some(value.to_string()),
25    })
26}
27
28pub fn deserialize_string_option<'de, D>(
29    deserializer: D,
30) -> Result<Option<compact_str::CompactString>, D::Error>
31where
32    D: Deserializer<'de>,
33{
34    let value: Option<compact_str::CompactString> =
35        Option::deserialize(deserializer).unwrap_or_default();
36    Ok(value.filter(|s| !s.is_empty()))
37}
38
39pub fn deserialize_array_or_not<'de, D, T: DeserializeOwned>(
40    deserializer: D,
41) -> Result<Vec<T>, D::Error>
42where
43    D: Deserializer<'de>,
44{
45    let value = serde_json::Value::deserialize(deserializer).unwrap_or_default();
46    let value: Vec<T> = match value {
47        serde_json::Value::Array(values) => {
48            serde_json::from_value(serde_json::Value::Array(values))
49                .map_err(serde::de::Error::custom)?
50        }
51        value => vec![serde_json::from_value(value).map_err(serde::de::Error::custom)?],
52    };
53
54    Ok(value)
55}
56
57pub fn deserialize_pre_stringified<'de, D, T: DeserializeOwned>(
58    deserializer: D,
59) -> Result<T, D::Error>
60where
61    D: Deserializer<'de>,
62{
63    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
64    let value: T = match value {
65        serde_json::Value::String(value) => {
66            serde_json::from_str(&value).map_err(serde::de::Error::custom)?
67        }
68        value => serde_json::from_value(value).map_err(serde::de::Error::custom)?,
69    };
70
71    Ok(value)
72}
73
74pub fn deserialize_nest_egg_config_stop<'de, D>(
75    deserializer: D,
76) -> Result<crate::models::nest_egg::NestEggConfigStop, D::Error>
77where
78    D: Deserializer<'de>,
79{
80    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
81    let value: crate::models::nest_egg::NestEggConfigStop = match value {
82        serde_json::Value::String(value) => serde_json::from_str(&value).unwrap_or_else(|_| {
83            crate::models::nest_egg::NestEggConfigStop {
84                r#type: if value == "^C" || value == "^^C" {
85                    "signal".into()
86                } else {
87                    "command".into()
88                },
89                value: Some(match value.as_str() {
90                    "^C" => "SIGINT".into(),
91                    "^^C" => "SIGKILL".into(),
92                    _ => value.into(),
93                }),
94            }
95        }),
96        value => serde_json::from_value(value).map_err(serde::de::Error::custom)?,
97    };
98
99    Ok(value)
100}
101
102pub fn deserialize_nest_egg_config_files<'de, D>(
103    deserializer: D,
104) -> Result<
105    IndexMap<compact_str::CompactString, crate::models::nest_egg::ExportedNestEggConfigsFilesFile>,
106    D::Error,
107>
108where
109    D: Deserializer<'de>,
110{
111    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
112    let value: serde_json::Value = match value {
113        serde_json::Value::String(value) => {
114            serde_json::from_str(&value).map_err(serde::de::Error::custom)?
115        }
116        value => value,
117    };
118
119    #[derive(Deserialize, Clone)]
120    pub struct OldExportedNestEggConfigsFilesFile {
121        pub parser: crate::models::nest_egg::ServerConfigurationFileParser,
122        pub find: IndexMap<compact_str::CompactString, serde_json::Value>,
123    }
124
125    if let Ok(value) = serde_json::from_value::<
126        IndexMap<compact_str::CompactString, OldExportedNestEggConfigsFilesFile>,
127    >(value.clone())
128    {
129        Ok(value
130            .into_iter()
131            .map(|(k, v)| {
132                (
133                    k,
134                    crate::models::nest_egg::ExportedNestEggConfigsFilesFile {
135                        create_new: true,
136                        parser: v.parser,
137                        replace: v
138                            .find
139                            .into_iter()
140                            .map(|(k, replace_with)| {
141                                crate::models::nest_egg::ProcessConfigurationFileReplacement {
142                                    r#match: k,
143                                    insert_new: !matches!(v.parser, crate::models::nest_egg::ServerConfigurationFileParser::File),
144                                    update_existing: true,
145                                    if_value: None,
146                                    replace_with,
147                                }
148                            })
149                            .collect(),
150                    },
151                )
152            })
153            .collect())
154    } else {
155        serde_json::from_value(value).map_err(serde::de::Error::custom)
156    }
157}
158
159pub fn deserialize_nest_egg_variable_rules<'de, D>(
160    deserializer: D,
161) -> Result<Vec<compact_str::CompactString>, D::Error>
162where
163    D: Deserializer<'de>,
164{
165    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
166    let value: Vec<compact_str::CompactString> = match value {
167        serde_json::Value::String(value) => value.split('|').map(|v| v.into()).collect(),
168        value => serde_json::from_value(value).map_err(serde::de::Error::custom)?,
169    };
170
171    Ok(value)
172}
173
174pub fn deserialize_public_key<'de, D>(deserializer: D) -> Result<russh::keys::PublicKey, D::Error>
175where
176    D: Deserializer<'de>,
177{
178    let value = <&str>::deserialize(deserializer)?;
179    let public_key = russh::keys::PublicKey::from_openssh(value)
180        .map_err(|_| serde::de::Error::custom("invalid public key"))?;
181
182    Ok(public_key)
183}