1#![warn(clippy::all, missing_docs, nonstandard_style, future_incompatible)]
40
41pub mod vec_num {
43 use serde::{self, de::Error, Deserialize, Deserializer, Serializer};
44 use std::{fmt::Display, str::FromStr};
45
46 pub fn serialize<S, T>(list: &[T], serializer: S) -> Result<S::Ok, S::Error>
48 where
49 S: Serializer,
50 T: ToString,
51 {
52 let s = list
53 .iter()
54 .map(ToString::to_string)
55 .collect::<Vec<_>>()
56 .join("_");
57 serializer.serialize_str(&s)
58 }
59
60 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
62 where
63 D: Deserializer<'de>,
64 T: FromStr + Display,
65 <T as FromStr>::Err: Display,
66 {
67 let s = String::deserialize(deserializer)?;
68 if s.is_empty() {
69 return Ok(Vec::new());
70 }
71 s.split('_')
72 .map(|n| n.parse().map_err(Error::custom))
73 .collect()
74 }
75}
76
77pub mod vec_vec_num {
79 use serde::{self, Deserialize, Deserializer, Serializer};
80 use std::{fmt::Display, str::FromStr};
81
82 pub fn serialize<S, T>(rows: &[Vec<T>], serializer: S) -> Result<S::Ok, S::Error>
84 where
85 S: Serializer,
86 T: ToString,
87 {
88 let s = rows
89 .iter()
90 .map(|c| {
91 c.iter()
92 .map(ToString::to_string)
93 .collect::<Vec<_>>()
94 .join("_")
95 })
96 .collect::<Vec<_>>()
97 .join("|");
98 serializer.serialize_str(&s)
99 }
100
101 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<Vec<T>>, D::Error>
103 where
104 D: Deserializer<'de>,
105 T: FromStr + Display,
106 <T as FromStr>::Err: Display,
107 {
108 let s = String::deserialize(deserializer)?;
109 if s.is_empty() {
110 return Ok(Vec::new());
111 }
112
113 let mut rows = Vec::new();
114 for line in s.split('|') {
115 let mut row = Vec::new();
116 for col_str in line.split('_') {
117 row.push(col_str.parse().map_err(serde::de::Error::custom)?)
118 }
119 rows.push(row);
120 }
121
122 Ok(rows)
123 }
124}
125
126pub mod maybe_image_size {
128 use serde::{self, de::Error, Deserialize, Deserializer, Serializer};
129 use std::{fmt::Display, str::FromStr};
130
131 pub fn serialize<S, W, H>(size: &Option<(W, H)>, serializer: S) -> Result<S::Ok, S::Error>
133 where
134 S: Serializer,
135 W: Display,
136 H: Display,
137 {
138 if let Some(size) = size {
139 let s = format!("{}x{}", size.0, size.1);
140 serializer.serialize_str(&s)
141 } else {
142 serializer.serialize_str("")
143 }
144 }
145
146 pub fn deserialize<'de, D, W, H>(deserializer: D) -> Result<Option<(W, H)>, D::Error>
148 where
149 D: Deserializer<'de>,
150 W: FromStr + Display,
151 <W as FromStr>::Err: Display,
152 H: FromStr + Display,
153 <H as FromStr>::Err: Display,
154 {
155 let s = String::deserialize(deserializer)?;
156 if s.is_empty() {
157 return Ok(None);
158 }
159 let (width, height) = s
160 .split_once("x")
161 .ok_or_else(|| Error::custom("bad image size format"))?;
162 Ok(Some((
163 width.parse().map_err(Error::custom)?,
164 height.parse().map_err(Error::custom)?,
165 )))
166 }
167}
168
169pub mod maybe_lat_lon {
171 use serde::{self, de::Error, Deserialize, Deserializer, Serializer};
172 use std::{fmt::Display, str::FromStr};
173
174 pub fn serialize<S, T>(size: &Option<(T, T)>, serializer: S) -> Result<S::Ok, S::Error>
176 where
177 S: Serializer,
178 T: Display,
179 {
180 if let Some(size) = size {
181 let s = format!("{};{}", size.0, size.1);
182 serializer.serialize_str(&s)
183 } else {
184 serializer.serialize_str("")
185 }
186 }
187
188 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Option<(T, T)>, D::Error>
190 where
191 D: Deserializer<'de>,
192 T: FromStr + Display,
193 <T as FromStr>::Err: Display,
194 {
195 let s = String::deserialize(deserializer)?;
196 if s.is_empty() {
197 return Ok(None);
198 }
199 let (lat, lon) = s
200 .split_once(";")
201 .ok_or_else(|| Error::custom("bad image size format"))?;
202 Ok(Some((
203 lat.parse().map_err(Error::custom)?,
204 lon.parse().map_err(Error::custom)?,
205 )))
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212 use serde::{Deserialize, Serialize};
213
214 #[test]
215 fn vec_i32() {
216 #[derive(Debug, Deserialize, Serialize, PartialEq)]
217 struct Foo(#[serde(with = "vec_num")] Vec<i32>);
218
219 let foo = Foo(vec![-1, 0, 3]);
220 let foo_str = "\"-1_0_3\"";
221
222 let serialized = serde_json::to_string(&foo).unwrap();
223 assert_eq!(serialized, foo_str);
224
225 let deserialized: Foo = serde_json::from_str(foo_str).unwrap();
226 assert_eq!(deserialized, foo);
227
228 let empty = Foo(vec![]);
229 let empty_str = "\"\"";
230
231 let serialized = serde_json::to_string(&empty).unwrap();
232 assert_eq!(serialized, empty_str);
233
234 let deserialized: Foo = serde_json::from_str(empty_str).unwrap();
235 assert_eq!(deserialized, empty);
236 }
237
238 #[test]
239 fn vec_vec_i32() {
240 #[derive(Debug, Deserialize, Serialize, PartialEq)]
241 struct Foo(#[serde(with = "vec_vec_num")] Vec<Vec<i32>>);
242
243 let foo = Foo(vec![vec![0], vec![-1, 1]]);
244 let foo_str = "\"0|-1_1\"";
245
246 let serialized = serde_json::to_string(&foo).unwrap();
247 assert_eq!(serialized, foo_str);
248
249 let deserialized: Foo = serde_json::from_str(foo_str).unwrap();
250 assert_eq!(deserialized, foo);
251
252 let empty = Foo(vec![]);
253 let empty_str = "\"\"";
254
255 let serialized = serde_json::to_string(&empty).unwrap();
256 assert_eq!(serialized, empty_str);
257
258 let deserialized: Foo = serde_json::from_str(empty_str).unwrap();
259 assert_eq!(deserialized, empty);
260 }
261
262 #[test]
263 fn img_size() {
264 #[derive(Debug, Deserialize, Serialize, PartialEq)]
265 struct Foo(#[serde(with = "maybe_image_size")] Option<(u8, u16)>);
266
267 let foo = Foo(Some((1, 2)));
268 let foo_str = "\"1x2\"";
269
270 let serialized = serde_json::to_string(&foo).unwrap();
271 assert_eq!(serialized, foo_str);
272
273 let deserialized: Foo = serde_json::from_str(foo_str).unwrap();
274 assert_eq!(deserialized, foo);
275
276 let empty = Foo(None);
277 let empty_str = "\"\"";
278
279 let serialized = serde_json::to_string(&empty).unwrap();
280 assert_eq!(serialized, empty_str);
281
282 let deserialized: Foo = serde_json::from_str(empty_str).unwrap();
283 assert_eq!(deserialized, empty);
284 }
285
286 #[test]
287 fn geo() {
288 #[derive(Debug, Deserialize, Serialize, PartialEq)]
289 struct Foo(#[serde(with = "maybe_lat_lon")] Option<(f32, f32)>);
290
291 let foo = Foo(Some((-1.1, 1.1)));
292 let foo_str = "\"-1.1;1.1\"";
293
294 let serialized = serde_json::to_string(&foo).unwrap();
295 assert_eq!(serialized, foo_str);
296
297 let deserialized: Foo = serde_json::from_str(foo_str).unwrap();
298 assert_eq!(deserialized, foo);
299
300 let empty = Foo(None);
301 let empty_str = "\"\"";
302
303 let serialized = serde_json::to_string(&empty).unwrap();
304 assert_eq!(serialized, empty_str);
305
306 let deserialized: Foo = serde_json::from_str(empty_str).unwrap();
307 assert_eq!(deserialized, empty);
308 }
309}