1use std::collections::*;
2
3use serde::{de, Deserialize};
4pub use trim_in_place::*;
5
6pub fn string_trim<'de, D>(d: D) -> Result<String, D::Error>
7where
8 D: de::Deserializer<'de>,
9{
10 let mut de_string = String::deserialize(d)?;
11 de_string.trim_in_place();
12 Ok(de_string)
13}
14
15pub fn option_string_trim<'de, D>(d: D) -> Result<Option<String>, D::Error>
16where
17 D: de::Deserializer<'de>,
18{
19 let mut de_string: Option<String> = Option::deserialize(d)?;
20 if let Some(ref mut de_string) = de_string {
21 if de_string.trim_in_place().is_empty() {
22 return Ok(None);
23 }
24 }
25 Ok(de_string)
26}
27
28macro_rules! iter_trim {
29 ($fn_name:ident,$t:ty) => {
30 pub fn $fn_name<'de, D>(d: D) -> Result<$t, D::Error>
31 where
32 D: de::Deserializer<'de>,
33 {
34 collection_trim(d)
35 }
36 };
37}
38
39macro_rules! iter_non_empty_trim {
40 ($fn_name:ident,$t:ty) => {
41 pub fn $fn_name<'de, D>(d: D) -> Result<$t, D::Error>
42 where
43 D: de::Deserializer<'de>,
44 {
45 collection_non_empty_trim(d)
46 }
47 };
48}
49
50iter_trim!(btreeset_string_trim, BTreeSet<String>);
51iter_trim!(vec_string_trim, Vec<String>);
52iter_trim!(hashset_string_trim, HashSet<String>);
53iter_trim!(vecdeque_string_trim, VecDeque<String>);
54iter_trim!(linkedlist_string_trim, LinkedList<String>);
55iter_trim!(binaryheap_string_trim, BinaryHeap<String>);
56
57iter_non_empty_trim!(btreeset_non_empty_string_trim, BTreeSet<String>);
58iter_non_empty_trim!(vec_non_empty_string_trim, Vec<String>);
59iter_non_empty_trim!(hashset_non_empty_string_trim, HashSet<String>);
60iter_non_empty_trim!(vecdeque_non_empty_string_trim, VecDeque<String>);
61iter_non_empty_trim!(linkedlist_non_empty_string_trim, LinkedList<String>);
62iter_non_empty_trim!(binaryheap_non_empty_string_trim, BinaryHeap<String>);
63
64fn collection_trim<'de, C, D, S>(d: D) -> Result<C, D::Error>
65where
66 S: TrimInPlace,
67 C: Deserialize<'de> + IntoIterator<Item = S> + FromIterator<String>,
68 D: de::Deserializer<'de>,
69{
70 let de_string: C = C::deserialize(d)?
71 .into_iter()
72 .map(|mut x| x.trim_in_place().to_string())
73 .collect();
74 Ok(de_string)
75}
76
77fn collection_non_empty_trim<'de, C, D, S>(d: D) -> Result<C, D::Error>
78where
79 S: TrimInPlace,
80 C: Deserialize<'de> + IntoIterator<Item = S> + FromIterator<String>,
81 D: de::Deserializer<'de>,
82{
83 let de_string: C = C::deserialize(d)?
84 .into_iter()
85 .filter_map(|mut x| {
86 let x = x.trim_in_place().to_string();
87 if x.is_empty() {
88 None
89 } else {
90 Some(x)
91 }
92 })
93 .collect();
94 Ok(de_string)
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_string_trim() {
103 #[derive(Deserialize)]
104 struct Foo {
105 #[serde(deserialize_with = "string_trim")]
106 name: String,
107 }
108 let json = r#"{"name":" "}"#;
109 let foo = serde_json::from_str::<Foo>(json).unwrap();
110 assert_eq!(foo.name, "");
111 }
112
113 #[test]
114 fn test_option_string_trim() {
115 #[derive(Deserialize)]
116 struct OptionFoo {
117 #[serde(deserialize_with = "option_string_trim")]
118 name: Option<String>,
119 }
120 let json = r#"{"name":" "}"#;
121 let foo = serde_json::from_str::<OptionFoo>(json).unwrap();
122 assert_eq!(foo.name, None);
123
124 #[derive(Deserialize)]
125 struct OptionBar {
126 #[serde(default, deserialize_with = "option_string_trim")]
127 name: Option<String>,
128 addr: String,
129 }
130 let json = r#"{"addr":"ABC"}"#;
131 let foo = serde_json::from_str::<OptionBar>(json).unwrap();
132 assert_eq!(foo.name, None);
133 assert_eq!(foo.addr, "ABC");
134 }
135
136 #[test]
137 fn test_vec_string_trim() {
138 #[derive(Deserialize)]
139 struct VecFoo {
140 #[serde(deserialize_with = "vec_string_trim")]
141 name: Vec<String>,
142 }
143 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
144 let foo = serde_json::from_str::<VecFoo>(json).unwrap();
145 assert_eq!(foo.name, vec!["", "foo", "b ar", "hello", "rust"]);
146 }
147
148 #[test]
149 fn test_btreeset_string_trim() {
150 #[derive(Deserialize)]
151 struct BTreeSetFoo {
152 #[serde(deserialize_with = "btreeset_string_trim")]
153 name: BTreeSet<String>,
154 }
155 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
156 let foo = serde_json::from_str::<BTreeSetFoo>(json).unwrap();
157 let expected: BTreeSet<String> = BTreeSet::from_iter([
158 "".into(),
159 "foo".into(),
160 "b ar".into(),
161 "hello".into(),
162 "rust".into(),
163 ]);
164 assert_eq!(foo.name, expected);
165 }
166
167 #[test]
168 fn test_hashset_string_trim() {
169 #[derive(Deserialize)]
170 struct HashSetFoo {
171 #[serde(deserialize_with = "hashset_string_trim")]
172 name: HashSet<String>,
173 }
174 let json = r#"{"name":[" ","foo","b ar","hello "," rust"," rust"]}"#;
175 let foo = serde_json::from_str::<HashSetFoo>(json).unwrap();
176 let expected: HashSet<String> = HashSet::from_iter([
177 "".into(),
178 "foo".into(),
179 "b ar".into(),
180 "hello".into(),
181 "rust".into(),
182 ]);
183 assert_eq!(foo.name, expected);
184 }
185
186 #[test]
187 fn test_vecdeque_string_trim() {
188 #[derive(Deserialize)]
189 struct VecDequeFoo {
190 #[serde(deserialize_with = "vecdeque_string_trim")]
191 name: VecDeque<String>,
192 }
193 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
194 let foo = serde_json::from_str::<VecDequeFoo>(json).unwrap();
195 assert_eq!(foo.name, vec!["", "foo", "b ar", "hello", "rust"]);
196 }
197
198 #[test]
199 fn test_linkedlist_string_trim() {
200 #[derive(Deserialize)]
201 struct LinkedListFoo {
202 #[serde(deserialize_with = "linkedlist_string_trim")]
203 name: LinkedList<String>,
204 }
205 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
206 let foo = serde_json::from_str::<LinkedListFoo>(json).unwrap();
207 assert_eq!(
208 foo.name,
209 LinkedList::from_iter([
210 "".into(),
211 "foo".into(),
212 "b ar".into(),
213 "hello".into(),
214 "rust".into(),
215 ])
216 );
217 }
218
219 #[test]
220 fn test_binaryheap_string_trim() {
221 #[derive(Deserialize)]
222 struct BinaryHeapFoo {
223 #[serde(deserialize_with = "binaryheap_string_trim")]
224 name: BinaryHeap<String>,
225 }
226 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
227 let foo = serde_json::from_str::<BinaryHeapFoo>(json).unwrap();
228 assert_eq!(
229 foo.name.into_vec(),
230 vec!["rust", "hello", "b ar", "", "foo"]
231 );
232 }
233
234 #[test]
235 fn test_vec_non_empty_string_trim() {
236 #[derive(Deserialize)]
237 struct VecFoo {
238 #[serde(deserialize_with = "vec_non_empty_string_trim")]
239 name: Vec<String>,
240 }
241 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
242 let foo = serde_json::from_str::<VecFoo>(json).unwrap();
243 assert_eq!(foo.name, vec!["foo", "b ar", "hello", "rust"]);
244 }
245
246 #[test]
247 fn test_btreeset_non_empty_string_trim() {
248 #[derive(Deserialize)]
249 struct BTreeSetFoo {
250 #[serde(deserialize_with = "btreeset_non_empty_string_trim")]
251 name: BTreeSet<String>,
252 }
253 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
254 let foo = serde_json::from_str::<BTreeSetFoo>(json).unwrap();
255 let expected: BTreeSet<String> =
256 BTreeSet::from_iter(["foo".into(), "b ar".into(), "hello".into(), "rust".into()]);
257 assert_eq!(foo.name, expected);
258 }
259
260 #[test]
261 fn test_hashset_non_empty_string_trim() {
262 #[derive(Deserialize)]
263 struct HashSetFoo {
264 #[serde(deserialize_with = "hashset_non_empty_string_trim")]
265 name: HashSet<String>,
266 }
267 let json = r#"{"name":[" ","foo","b ar","hello "," rust"," rust"]}"#;
268 let foo = serde_json::from_str::<HashSetFoo>(json).unwrap();
269 let expected: HashSet<String> =
270 HashSet::from_iter(["foo".into(), "b ar".into(), "hello".into(), "rust".into()]);
271 assert_eq!(foo.name, expected);
272 }
273
274 #[test]
275 fn test_vecdeque_non_empty_string_trim() {
276 #[derive(Deserialize)]
277 struct VecDequeFoo {
278 #[serde(deserialize_with = "vecdeque_non_empty_string_trim")]
279 name: VecDeque<String>,
280 }
281 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
282 let foo = serde_json::from_str::<VecDequeFoo>(json).unwrap();
283 assert_eq!(foo.name, vec!["foo", "b ar", "hello", "rust"]);
284 }
285
286 #[test]
287 fn test_linkedlist_non_empty_string_trim() {
288 #[derive(Deserialize)]
289 struct LinkedListFoo {
290 #[serde(deserialize_with = "linkedlist_non_empty_string_trim")]
291 name: LinkedList<String>,
292 }
293 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
294 let foo = serde_json::from_str::<LinkedListFoo>(json).unwrap();
295 assert_eq!(
296 foo.name,
297 LinkedList::from_iter(["foo".into(), "b ar".into(), "hello".into(), "rust".into(),])
298 );
299 }
300
301 #[test]
302 fn test_binaryheap_non_empty_string_trim() {
303 #[derive(Deserialize)]
304 struct BinaryHeapFoo {
305 #[serde(deserialize_with = "binaryheap_non_empty_string_trim")]
306 name: BinaryHeap<String>,
307 }
308 let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
309 let foo = serde_json::from_str::<BinaryHeapFoo>(json).unwrap();
310 assert_eq!(foo.name.into_vec(), vec!["rust", "hello", "b ar", "foo"]);
311 }
312}