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}