Skip to main content

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_map_or_not<
58    'de,
59    D,
60    K: DeserializeOwned + std::hash::Hash + Eq,
61    V: DeserializeOwned,
62>(
63    deserializer: D,
64) -> Result<IndexMap<K, V>, D::Error>
65where
66    D: Deserializer<'de>,
67{
68    let value = serde_json::Value::deserialize(deserializer).unwrap_or_default();
69    let value: IndexMap<K, V> = match value {
70        serde_json::Value::Object(map) => serde_json::from_value(serde_json::Value::Object(map))
71            .map_err(serde::de::Error::custom)?,
72        value => {
73            let v = serde_json::from_value(value).map_err(serde::de::Error::custom)?;
74            let mut map = IndexMap::new();
75            map.insert(
76                K::deserialize(serde_json::Value::String("Default".into()))
77                    .map_err(serde::de::Error::custom)?,
78                v,
79            );
80            map
81        }
82    };
83
84    Ok(value)
85}
86
87pub fn deserialize_pre_stringified<'de, D, T: DeserializeOwned>(
88    deserializer: D,
89) -> Result<T, D::Error>
90where
91    D: Deserializer<'de>,
92{
93    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
94    let value: T = match value {
95        serde_json::Value::String(value) => {
96            serde_json::from_str(&value).map_err(serde::de::Error::custom)?
97        }
98        value => serde_json::from_value(value).map_err(serde::de::Error::custom)?,
99    };
100
101    Ok(value)
102}
103
104pub fn deserialize_nest_egg_config_stop<'de, D>(
105    deserializer: D,
106) -> Result<crate::models::nest_egg::NestEggConfigStop, D::Error>
107where
108    D: Deserializer<'de>,
109{
110    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
111    let value: crate::models::nest_egg::NestEggConfigStop = match value {
112        serde_json::Value::String(value) => serde_json::from_str(&value).unwrap_or_else(|_| {
113            crate::models::nest_egg::NestEggConfigStop {
114                r#type: if value == "^C" || value == "^^C" {
115                    "signal".into()
116                } else {
117                    "command".into()
118                },
119                value: Some(match value.as_str() {
120                    "^C" => "SIGINT".into(),
121                    "^^C" => "SIGKILL".into(),
122                    _ => value.into(),
123                }),
124            }
125        }),
126        value => serde_json::from_value(value).map_err(serde::de::Error::custom)?,
127    };
128
129    Ok(value)
130}
131
132pub fn deserialize_nest_egg_config_files<'de, D>(
133    deserializer: D,
134) -> Result<
135    IndexMap<compact_str::CompactString, crate::models::nest_egg::ExportedNestEggConfigsFilesFile>,
136    D::Error,
137>
138where
139    D: Deserializer<'de>,
140{
141    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
142    let value: serde_json::Value = match value {
143        serde_json::Value::String(value) => serde_json::from_str(&value).unwrap_or_default(),
144        value => value,
145    };
146
147    #[derive(Deserialize, Clone)]
148    pub struct OldExportedNestEggConfigsFilesFile {
149        pub parser: crate::models::nest_egg::ServerConfigurationFileParser,
150        pub find: IndexMap<compact_str::CompactString, serde_json::Value>,
151    }
152
153    if let Ok(value) = serde_json::from_value::<
154        IndexMap<compact_str::CompactString, OldExportedNestEggConfigsFilesFile>,
155    >(value.clone())
156    {
157        Ok(value
158            .into_iter()
159            .map(|(k, v)| {
160                (
161                    k,
162                    crate::models::nest_egg::ExportedNestEggConfigsFilesFile {
163                        create_new: true,
164                        parser: v.parser,
165                        replace: v
166                            .find
167                            .into_iter()
168                            .map(|(k, replace_with)| {
169                                crate::models::nest_egg::ProcessConfigurationFileReplacement {
170                                    r#match: k,
171                                    insert_new: !matches!(v.parser, crate::models::nest_egg::ServerConfigurationFileParser::File),
172                                    update_existing: true,
173                                    if_value: None,
174                                    replace_with,
175                                }
176                            })
177                            .collect(),
178                    },
179                )
180            })
181            .collect())
182    } else {
183        serde_json::from_value(value).map_err(serde::de::Error::custom)
184    }
185}
186
187pub fn deserialize_nest_egg_variable_rules<'de, D>(
188    deserializer: D,
189) -> Result<Vec<compact_str::CompactString>, D::Error>
190where
191    D: Deserializer<'de>,
192{
193    let value: serde_json::Value = serde_json::Value::deserialize(deserializer)?;
194    let value: Vec<compact_str::CompactString> = match value {
195        serde_json::Value::String(value) => value.split('|').map(|v| v.into()).collect(),
196        value => serde_json::from_value(value).map_err(serde::de::Error::custom)?,
197    };
198
199    Ok(value)
200}
201
202pub fn deserialize_public_key<'de, D>(deserializer: D) -> Result<russh::keys::PublicKey, D::Error>
203where
204    D: Deserializer<'de>,
205{
206    let value = <&str>::deserialize(deserializer)?;
207    let public_key = russh::keys::PublicKey::from_openssh(value)
208        .map_err(|_| serde::de::Error::custom("invalid public key"))?;
209
210    Ok(public_key)
211}