1use alloc::collections::{BTreeMap, BTreeSet, LinkedList};
2use alloc::format;
3use alloc::string::{String, ToString};
4use alloc::vec::Vec;
5
6pub trait Serialize {
23 fn serialize(&self) -> String;
24}
25
26macro_rules! ser_primitives {
27 ( $( $name:ty ),+ ) => {
28 $(
29 impl Serialize for $name
30 {
31 fn serialize(&self) -> String {
32 format!("{:?}", self)
33 }
34 }
35 )+
36 };
37}
38
39impl<T> Serialize for Vec<T>
40where
41 T: Serialize,
42{
43 fn serialize(&self) -> String {
44 let aux_vec = self
45 .iter()
46 .map(Serialize::serialize)
47 .collect::<Vec<String>>();
48 let mut s = String::new();
49 s.push('[');
50 s.push_str(&aux_vec.join(", "));
51 s.push(']');
52 s
53 }
54}
55
56#[cfg(feature = "std")]
57impl<T, H: std::hash::BuildHasher> Serialize for std::collections::HashSet<T, H>
58where
59 T: Serialize,
60{
61 fn serialize(&self) -> String {
62 let aux_vec = self
63 .iter()
64 .map(Serialize::serialize)
65 .collect::<Vec<String>>();
66 let mut s = String::new();
67 s.push('#');
68 s.push('{');
69 s.push_str(&aux_vec.join(", "));
70 s.push('}');
71 s
72 }
73}
74
75impl<T> Serialize for BTreeSet<T>
76where
77 T: Serialize,
78{
79 fn serialize(&self) -> String {
80 let aux_vec = self
81 .iter()
82 .map(Serialize::serialize)
83 .collect::<Vec<String>>();
84 let mut s = String::new();
85 s.push('#');
86 s.push('{');
87 s.push_str(&aux_vec.join(", "));
88 s.push('}');
89 s
90 }
91}
92
93impl<T> Serialize for LinkedList<T>
94where
95 T: Serialize,
96{
97 fn serialize(&self) -> String {
98 let aux_vec = self
99 .iter()
100 .map(Serialize::serialize)
101 .collect::<Vec<String>>();
102 let mut s = String::new();
103 s.push('(');
104 s.push_str(&aux_vec.join(", "));
105 s.push(')');
106 s
107 }
108}
109
110#[cfg(feature = "std")]
111impl<T, H: std::hash::BuildHasher> Serialize for std::collections::HashMap<String, T, H>
112where
113 T: Serialize,
114{
115 fn serialize(&self) -> String {
116 let aux_vec = self
117 .iter()
118 .map(|(k, v)| format!(":{} {}", k.replace([' ', '_'], "-"), v.serialize()))
119 .collect::<Vec<String>>();
120 let mut s = String::new();
121 s.push('{');
122 s.push_str(&aux_vec.join(", "));
123 s.push('}');
124 s
125 }
126}
127
128#[cfg(feature = "std")]
129impl<T, H: ::std::hash::BuildHasher> Serialize for std::collections::HashMap<&str, T, H>
130where
131 T: Serialize,
132{
133 fn serialize(&self) -> String {
134 let aux_vec = self
135 .iter()
136 .map(|(k, v)| format!(":{} {}", k.replace([' ', '_'], "-"), v.serialize()))
137 .collect::<Vec<String>>();
138 let mut s = String::new();
139 s.push('{');
140 s.push_str(&aux_vec.join(", "));
141 s.push('}');
142 s
143 }
144}
145
146impl<T> Serialize for BTreeMap<String, T>
147where
148 T: Serialize,
149{
150 fn serialize(&self) -> String {
151 let aux_vec = self
152 .iter()
153 .map(|(k, v)| format!(":{} {}", k.replace([' ', '_'], "-"), v.serialize()))
154 .collect::<Vec<String>>();
155 let mut s = String::new();
156 s.push('{');
157 s.push_str(&aux_vec.join(", "));
158 s.push('}');
159 s
160 }
161}
162
163impl<T> Serialize for BTreeMap<&str, T>
164where
165 T: Serialize,
166{
167 fn serialize(&self) -> String {
168 let aux_vec = self
169 .iter()
170 .map(|(k, v)| format!(":{} {}", k.replace([' ', '_'], "-"), v.serialize()))
171 .collect::<Vec<String>>();
172 let mut s = String::new();
173 s.push('{');
174 s.push_str(&aux_vec.join(", "));
175 s.push('}');
176 s
177 }
178}
179
180ser_primitives![i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, bool];
182
183impl Serialize for () {
184 fn serialize(&self) -> String {
185 "nil".to_string()
186 }
187}
188
189impl Serialize for String {
190 fn serialize(&self) -> String {
191 format!("{self:?}")
192 }
193}
194
195impl Serialize for &str {
196 fn serialize(&self) -> String {
197 format!("{self:?}")
198 }
199}
200
201impl Serialize for char {
202 fn serialize(&self) -> String {
203 format!("\\{self}")
204 }
205}
206
207impl<T> Serialize for Option<T>
208where
209 T: Serialize,
210{
211 fn serialize(&self) -> String {
212 self.as_ref().map_or_else(
213 || String::from("nil"),
214 crate::serialize::Serialize::serialize,
215 )
216 }
217}
218
219impl<A: Serialize> Serialize for (A,) {
221 fn serialize(&self) -> String {
222 format!("({})", self.0.serialize())
223 }
224}
225
226impl<A: Serialize, B: Serialize> Serialize for (A, B) {
227 fn serialize(&self) -> String {
228 format!("({}, {})", self.0.serialize(), self.1.serialize())
229 }
230}
231
232impl<A: Serialize, B: Serialize, C: Serialize> Serialize for (A, B, C) {
233 fn serialize(&self) -> String {
234 format!(
235 "({}, {}, {})",
236 self.0.serialize(),
237 self.1.serialize(),
238 self.2.serialize()
239 )
240 }
241}
242
243impl<A: Serialize, B: Serialize, C: Serialize, D: Serialize> Serialize for (A, B, C, D) {
244 fn serialize(&self) -> String {
245 format!(
246 "({}, {}, {}, {})",
247 self.0.serialize(),
248 self.1.serialize(),
249 self.2.serialize(),
250 self.3.serialize()
251 )
252 }
253}
254
255impl<A: Serialize, B: Serialize, C: Serialize, D: Serialize, E: Serialize> Serialize
256 for (A, B, C, D, E)
257{
258 fn serialize(&self) -> String {
259 format!(
260 "({}, {}, {}, {}, {})",
261 self.0.serialize(),
262 self.1.serialize(),
263 self.2.serialize(),
264 self.3.serialize(),
265 self.4.serialize()
266 )
267 }
268}
269
270impl<A: Serialize, B: Serialize, C: Serialize, D: Serialize, E: Serialize, F: Serialize> Serialize
271 for (A, B, C, D, E, F)
272{
273 fn serialize(&self) -> String {
274 format!(
275 "({}, {}, {}, {}, {}, {})",
276 self.0.serialize(),
277 self.1.serialize(),
278 self.2.serialize(),
279 self.3.serialize(),
280 self.4.serialize(),
281 self.5.serialize()
282 )
283 }
284}
285
286#[cfg(test)]
287mod test {
288 use alloc::collections::BTreeSet;
289 use alloc::vec;
290
291 use super::*;
292
293 #[test]
294 fn unit() {
295 assert_eq!(().serialize(), "nil");
296 }
297
298 #[test]
299 fn primitive_types() {
300 let i = -34i32;
301 assert_eq!(i.serialize(), String::from("-34"));
302 assert_eq!('c'.serialize(), String::from("\\c"));
303 assert_eq!(8i8.serialize(), String::from("8"));
304 assert_eq!(8i16.serialize(), String::from("8"));
305 assert_eq!(8i32.serialize(), String::from("8"));
306 assert_eq!(8i64.serialize(), String::from("8"));
307 assert_eq!(8i64.serialize(), String::from("8"));
308 assert_eq!(8isize.serialize(), String::from("8"));
309 assert_eq!(128u8.serialize(), String::from("128"));
310 assert_eq!(128u16.serialize(), String::from("128"));
311 assert_eq!(128u32.serialize(), String::from("128"));
312 assert_eq!(128u64.serialize(), String::from("128"));
313 assert_eq!(128u64.serialize(), String::from("128"));
314 assert_eq!(128usize.serialize(), String::from("128"));
315 assert_eq!(true.serialize(), String::from("true"));
316 }
317
318 #[test]
319 fn tuples() {
320 let t2 = (12i32, 3.5f32);
321 let t3 = (12i32, 3.5f32, "oi");
322 let t4 = (12i32, 3.5f32, "oi", 'd');
323
324 assert_eq!(t2.serialize(), "(12, 3.5)");
325 assert_eq!(t3.serialize(), "(12, 3.5, \"oi\")");
326 assert_eq!(t4.serialize(), "(12, 3.5, \"oi\", \\d)");
327 }
328
329 #[test]
330 fn vectors() {
331 let v_i8 = vec![3i8, 12i8, 24i8, 72i8];
332 let v_u16 = vec![3u16, 12u16, 24u16, 72u16];
333 let v_f32 = vec![3.0f32, 12.1f32, 24.2f32, 72.3f32];
334 let v_i64 = vec![3i64, 12i64, 24i64, 72i64];
335 let v_u64 = vec![3u64, 12u64, 24u64, 72u64];
336 let v_bool = vec![true, false];
337
338 assert_eq!(v_i8.serialize(), "[3, 12, 24, 72]");
339 assert_eq!(v_u16.serialize(), "[3, 12, 24, 72]");
340 assert_eq!(v_f32.serialize(), "[3.0, 12.1, 24.2, 72.3]");
341 assert_eq!(v_i64.serialize(), "[3, 12, 24, 72]");
342 assert_eq!(v_u64.serialize(), "[3, 12, 24, 72]");
343 assert_eq!(v_bool.serialize(), "[true, false]");
344 }
345
346 #[test]
347 fn literals_vec() {
348 let v_str = vec!["aba", "cate", "azul"];
349 let v_string = vec!["aba".to_string(), "cate".to_string(), "azul".to_string()];
350
351 assert_eq!(v_str.serialize(), "[\"aba\", \"cate\", \"azul\"]");
352 assert_eq!(v_string.serialize(), "[\"aba\", \"cate\", \"azul\"]");
353 }
354
355 #[test]
356 fn hashsets() {
357 use alloc::collections::BTreeSet;
358
359 let set_i8 = (vec![3i8, 12i8, 24i8, 72i8]
360 .into_iter()
361 .collect::<BTreeSet<i8>>())
362 .serialize();
363 let set_u16 = (vec![3u16, 12u16, 24u16, 72u16]
364 .into_iter()
365 .collect::<BTreeSet<u16>>())
366 .serialize();
367 let set_i64 = (vec![3i64, 12i64, 24i64, 72i64]
368 .into_iter()
369 .collect::<BTreeSet<i64>>())
370 .serialize();
371 let set_bool = (vec![true, false].into_iter().collect::<BTreeSet<bool>>()).serialize();
372 let set_str = (vec!["aba", "cate", "azul"]
373 .into_iter()
374 .collect::<BTreeSet<&str>>())
375 .serialize();
376 let set_string = (vec!["aba".to_string(), "cate".to_string(), "azul".to_string()]
377 .into_iter()
378 .collect::<BTreeSet<String>>())
379 .serialize();
380
381 assert!(
382 set_i8.contains("#{")
383 && set_i8.contains(',')
384 && set_i8.contains('3')
385 && set_i8.contains('}')
386 );
387 assert!(
388 set_u16.contains("#{")
389 && set_u16.contains(',')
390 && set_u16.contains('3')
391 && set_u16.contains('}')
392 );
393 assert!(
394 set_i64.contains("#{")
395 && set_i64.contains(',')
396 && set_i64.contains('3')
397 && set_i64.contains('}')
398 );
399 assert!(
400 set_bool.contains("#{")
401 && set_bool.contains(',')
402 && set_bool.contains("true")
403 && set_bool.contains("false")
404 && set_bool.contains('}')
405 );
406 assert!(
407 set_str.contains("#{")
408 && set_str.contains(',')
409 && set_str.contains("\"aba\"")
410 && set_str.contains("\"cate\"")
411 && set_str.contains('}')
412 );
413 assert!(
414 set_string.contains("#{")
415 && set_string.contains(',')
416 && set_string.contains("\"aba\"")
417 && set_string.contains("\"cate\"")
418 && set_string.contains('}')
419 );
420 }
421
422 #[test]
423 fn btreesets() {
424 let set_i8 = (vec![3i8, 12i8, 24i8, 72i8]
425 .into_iter()
426 .collect::<BTreeSet<i8>>())
427 .serialize();
428 let set_u16 = (vec![3u16, 12u16, 24u16, 72u16]
429 .into_iter()
430 .collect::<BTreeSet<u16>>())
431 .serialize();
432 let set_i64 = (vec![3i64, 12i64, 24i64, 72i64]
433 .into_iter()
434 .collect::<BTreeSet<i64>>())
435 .serialize();
436 let set_bool = (vec![true, false].into_iter().collect::<BTreeSet<bool>>()).serialize();
437 let set_str = (vec!["aba", "cate", "azul"]
438 .into_iter()
439 .collect::<BTreeSet<&str>>())
440 .serialize();
441 let set_string = (vec!["aba".to_string(), "cate".to_string(), "azul".to_string()]
442 .into_iter()
443 .collect::<BTreeSet<String>>())
444 .serialize();
445
446 assert!(
447 set_i8.contains("#{")
448 && set_i8.contains(',')
449 && set_i8.contains('3')
450 && set_i8.contains('}')
451 );
452 assert!(
453 set_u16.contains("#{")
454 && set_u16.contains(',')
455 && set_u16.contains('3')
456 && set_u16.contains('}')
457 );
458 assert!(
459 set_i64.contains("#{")
460 && set_i64.contains(',')
461 && set_i64.contains('3')
462 && set_i64.contains('}')
463 );
464 assert!(
465 set_bool.contains("#{")
466 && set_bool.contains(',')
467 && set_bool.contains("true")
468 && set_bool.contains("false")
469 && set_bool.contains('}')
470 );
471 assert!(
472 set_str.contains("#{")
473 && set_str.contains(',')
474 && set_str.contains("\"aba\"")
475 && set_str.contains("\"cate\"")
476 && set_str.contains('}')
477 );
478 assert!(
479 set_string.contains("#{")
480 && set_string.contains(',')
481 && set_string.contains("\"aba\"")
482 && set_string.contains("\"cate\"")
483 && set_string.contains('}')
484 );
485 }
486
487 #[test]
488 fn lists() {
489 use alloc::collections::LinkedList;
490
491 let list_i8 = (vec![3i8, 12i8, 24i8, 72i8]
492 .into_iter()
493 .collect::<LinkedList<i8>>())
494 .serialize();
495 let list_u16 = (vec![3u16, 12u16, 24u16, 72u16]
496 .into_iter()
497 .collect::<LinkedList<u16>>())
498 .serialize();
499 let list_i64 = (vec![3i64, 12i64, 24i64, 72i64]
500 .into_iter()
501 .collect::<LinkedList<i64>>())
502 .serialize();
503 let list_f64 = (vec![3.1f64, 12.2f64, 24.3f64, 72.4f64]
504 .into_iter()
505 .collect::<LinkedList<f64>>())
506 .serialize();
507 let list_bool = (vec![true, false].into_iter().collect::<LinkedList<bool>>()).serialize();
508 let list_str = (vec!["aba", "cate", "azul"]
509 .into_iter()
510 .collect::<LinkedList<&str>>())
511 .serialize();
512 let list_string = (vec!["aba".to_string(), "cate".to_string(), "azul".to_string()]
513 .into_iter()
514 .collect::<LinkedList<String>>())
515 .serialize();
516
517 assert_eq!(list_i8, "(3, 12, 24, 72)");
518 assert_eq!(list_u16, "(3, 12, 24, 72)");
519 assert_eq!(list_i64, "(3, 12, 24, 72)");
520 assert_eq!(list_f64, "(3.1, 12.2, 24.3, 72.4)");
521 assert_eq!(list_bool, "(true, false)");
522 assert_eq!(list_str, "(\"aba\", \"cate\", \"azul\")");
523 assert_eq!(list_string, "(\"aba\", \"cate\", \"azul\")");
524 }
525
526 #[test]
527 fn hashmap() {
528 let m_i64 = map! {"hello world" => 5i64, "bye_bye" => 125i64}.serialize();
529 let m_bool =
530 map! {"hello world".to_string() => true, "bye_bye".to_string() => false}.serialize();
531 let m_str = map!{"hello world".to_string() => "this is str 1", "bye_bye".to_string() => "this is str 2"}.serialize();
532
533 assert!(
534 m_i64.contains(":hello-world 5")
535 && m_i64.contains(":bye-bye 125")
536 && m_i64.contains('{')
537 && m_i64.contains('}')
538 );
539 assert!(
540 m_bool.contains(":hello-world true")
541 && m_bool.contains(":bye-bye false")
542 && m_bool.contains('{')
543 && m_bool.contains('}')
544 );
545 assert!(
546 m_str.contains(":hello-world \"this is str 1\"")
547 && m_str.contains(":bye-bye \"this is str 2\"")
548 && m_str.contains('{')
549 && m_str.contains('}')
550 );
551 }
552
553 #[test]
554 fn multi_sized_tuples() {
555 assert_eq!((1,).serialize(), "(1)");
556 assert_eq!((1, "cool").serialize(), "(1, \"cool\")");
557 assert_eq!((1, "cool", false).serialize(), "(1, \"cool\", false)");
558 assert_eq!(
559 (1, "cool", false, 'z').serialize(),
560 "(1, \"cool\", false, \\z)"
561 );
562 assert_eq!(
563 (1, "cool", false, 'z', None::<String>).serialize(),
564 "(1, \"cool\", false, \\z, nil)"
565 );
566 }
567}