1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
6pub struct Trace {
7 pub packages: BTreeMap<String, PkgTrace>,
8}
9
10#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
11pub struct PkgTrace {
12 pub directory: String,
13
14 #[serde(with = "trace_map_as_map")]
15 pub maps: BTreeMap<String, String>,
16}
17
18impl PkgTrace {
19 pub fn new(directory: String) -> Self {
20 Self {
21 directory,
22 maps: BTreeMap::new(),
23 }
24 }
25}
26
27#[derive(Debug, Clone, Deserialize, Serialize)]
28struct TraceMap {
29 pub src: String,
30 pub dst: String,
31}
32
33mod trace_map_as_map {
34 use serde::{Deserializer, Serializer};
35
36 use super::*;
37
38 pub fn serialize<S>(map: &BTreeMap<String, String>, serializer: S) -> Result<S::Ok, S::Error>
39 where
40 S: Serializer,
41 {
42 let v: Vec<TraceMap> = map
43 .iter()
44 .map(|(src, dst)| TraceMap {
45 src: src.clone(),
46 dst: dst.clone(),
47 })
48 .collect();
49 v.serialize(serializer)
50 }
51
52 pub fn deserialize<'de, D>(deserializer: D) -> Result<BTreeMap<String, String>, D::Error>
53 where
54 D: Deserializer<'de>,
55 {
56 let v = Vec::<TraceMap>::deserialize(deserializer)?;
57 Ok(v.into_iter().map(|m| (m.src, m.dst)).collect())
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use serde_test::{Token, assert_tokens};
64
65 use super::*;
66
67 #[test]
68 fn pkg_trace_ser_de() {
69 let trace = PkgTrace {
70 directory: "test_dir".to_string(),
71 maps: BTreeMap::from([
72 ("src1".to_string(), "dst1".to_string()),
73 ("src2".to_string(), "dst2".to_string()),
74 ]),
75 };
76
77 assert_tokens(
78 &trace,
79 &[
80 Token::Struct {
81 name: "PkgTrace",
82 len: 2,
83 },
84 Token::Str("directory"),
85 Token::Str("test_dir"),
86 Token::Str("maps"),
87 Token::Seq { len: Some(2) },
88 Token::Struct {
89 name: "TraceMap",
90 len: 2,
91 },
92 Token::Str("src"),
93 Token::Str("src1"),
94 Token::Str("dst"),
95 Token::Str("dst1"),
96 Token::StructEnd,
97 Token::Struct {
98 name: "TraceMap",
99 len: 2,
100 },
101 Token::Str("src"),
102 Token::Str("src2"),
103 Token::Str("dst"),
104 Token::Str("dst2"),
105 Token::StructEnd,
106 Token::SeqEnd,
107 Token::StructEnd,
108 ],
109 )
110 }
111}