1use can_dbc::{ByteOrder, Comment, Dbc, Message, Node, Signal, Transmitter, ValueType};
2
3pub fn dbc_to_string(dbc: &Dbc) -> String {
4 let mut lines = Vec::new();
5
6 lines.push(format!("VERSION \"{}\"\n", dbc.version.0));
7
8 lines.push(String::from(
9 r#"NS_:
10 NS_DESC_
11 CM_
12 BA_DEF_
13 BA_
14 VAL_
15 CAT_DEF_
16 CAT_
17 FILTER
18 BA_DEF_DEF_
19 EV_DATA_
20 ENVVAR_DATA_
21 SGTYPE_
22 SGTYPE_VAL_
23 BA_DEF_SGTYPE_
24 BA_SGTYPE_
25 SIG_TYPE_REF_
26 VAL_TABLE_
27 SIG_GROUP_
28 SIG_VALTYPE_
29 SIGTYPE_VALTYPE_
30 BO_TX_BU_
31 BA_DEF_REL_
32 BA_REL_
33 BA_DEF_DEF_REL_
34 BU_SG_REL_
35 BU_EV_REL_
36 BU_BO_REL_
37 SG_MUL_VAL_"#,
38 ));
39
40 lines.push(String::from("BS:\n"));
41
42 lines.push(format!("{}\n", nodes_to_string(&dbc.nodes)));
43 lines.push(format!("{}\n", messages_to_string(&dbc.messages)));
44 lines.push(format!("{}\n", comments_to_string(&dbc.comments)));
45
46 lines.push(String::from(
47 r#"BA_DEF_ "BusType" STRING ;
48BA_DEF_ "DatabaseCompiler" STRING ;
49BA_DEF_ "DatabaseVersion" STRING ;
50BA_DEF_ "ProtocolType" STRING ;
51BA_ "BusType" "CAN";
52BA_ "DatabaseCompiler" "Kent Software (kent.software)";
53BA_ "DatabaseVersion" "1.0.0";
54BA_ "ProtocolType" "J1939";"#,
55 ));
56
57 lines.join("\n")
58}
59
60pub fn nodes_to_string(nodes: &[Node]) -> String {
61 let mut lines = Vec::new();
62
63 lines.push(String::from("BU_:"));
64
65 for node in nodes {
66 lines.push(format!("\t{}", node.0));
67 }
68
69 lines.join("\n")
70}
71
72pub fn messages_to_string(messages: &[Message]) -> String {
73 let mut message_lines = Vec::new();
74
75 for message in messages {
76 message_lines.push(message_to_string(message));
77 }
78
79 message_lines.join("\n")
80}
81
82pub fn message_to_string(message: &Message) -> String {
83 let mut lines = Vec::new();
84
85 lines.push(format!(
86 "BO_ {} {}: {} {}",
87 message.id.raw(),
88 message.name,
89 message.size,
90 match &message.transmitter {
91 Transmitter::NodeName(node_name) => {
92 node_name.clone()
93 }
94 Transmitter::VectorXXX => {
95 String::from("Vector__XXX")
96 }
97 }
98 ));
99
100 for signal in &message.signals {
101 lines.push(format!("\t{}", signal_to_string(&signal)));
102 }
103
104 lines.join("\n")
105}
106
107pub fn signal_to_string(signal: &Signal) -> String {
108 format!(
109 "SG_ {} : {}|{}@{}{} ({},{}) [{}|{}] \"{}\" {}",
110 signal.name,
111 signal.start_bit,
112 signal.size,
113 match signal.byte_order {
114 ByteOrder::BigEndian => 0,
115 ByteOrder::LittleEndian => 1,
116 },
117 match signal.value_type {
118 ValueType::Signed => "-",
119 ValueType::Unsigned => "+",
120 },
121 signal.factor,
122 signal.offset,
123 signal.min,
124 signal.max,
125 signal.unit,
126 signal.receivers.join(","),
127 )
128}
129
130pub fn comments_to_string(comments: &[Comment]) -> String {
131 let mut comment_lines = Vec::new();
132
133 for comment in comments {
134 comment_lines.push(comment_to_string(comment));
135 }
136
137 comment_lines.join("\n")
138}
139
140pub fn comment_to_string(comment: &Comment) -> String {
141 match comment {
142 Comment::EnvVar { name, comment } => {
143 format!("CM_ EV_ {} \"{}\";", name, comment,)
144 }
145 Comment::Message { id, comment } => {
146 format!("CM_ BO_ {} \"{}\";", id.raw(), comment,)
147 }
148 Comment::Node { name, comment } => {
149 format!("CM_ BU_ {} \"{}\";", name, comment,)
150 }
151 Comment::Plain { comment } => {
152 format!("CM_ \"{}\";", comment,)
153 }
154 Comment::Signal {
155 message_id,
156 name,
157 comment,
158 } => {
159 format!("CM_ SG_ {} {} \"{}\";", message_id.raw(), name, comment,)
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use can_dbc::{MessageId, MultiplexIndicator, Transmitter};
167
168 use super::*;
169
170 #[test]
171 fn test_comments() {
172 assert_eq!(
173 comment_to_string(&Comment::EnvVar {
174 name: String::from("name"),
175 comment: String::from("comment"),
176 }),
177 r#"CM_ EV_ name "comment";"#
178 );
179
180 assert_eq!(
181 comment_to_string(&Comment::Node {
182 name: String::from("name"),
183 comment: String::from("comment"),
184 }),
185 r#"CM_ BU_ name "comment";"#
186 );
187
188 assert_eq!(
189 comment_to_string(&Comment::Message {
190 id: MessageId::Extended(0),
191 comment: String::from("comment"),
192 }),
193 r#"CM_ BO_ 2147483648 "comment";"#
194 );
195
196 assert_eq!(
197 comment_to_string(&Comment::Plain {
198 comment: String::from("comment"),
199 }),
200 r#"CM_ "comment";"#
201 );
202
203 assert_eq!(
204 comment_to_string(&Comment::Signal {
205 message_id: MessageId::Extended(0),
206 name: String::from("name"),
207 comment: String::from("comment"),
208 }),
209 r#"CM_ SG_ 2147483648 name "comment";"#
210 );
211 }
212
213 #[test]
214 pub fn test_signal() {
215 assert_eq!(
216 signal_to_string(&Signal {
217 name: String::from("name"),
218 multiplexer_indicator: MultiplexIndicator::Plain,
219 start_bit: 0,
220 size: 1,
221 byte_order: ByteOrder::BigEndian,
222 value_type: ValueType::Unsigned,
223 factor: 1.5,
224 offset: 2.5,
225 min: -10.0,
226 max: 10.0,
227 unit: String::from("unit"),
228 receivers: vec![String::from("Vector__XXX")]
229 }),
230 r#"SG_ name : 0|1@0+ (1.5,2.5) [-10|10] "unit" Vector__XXX"#
231 );
232 }
233
234 #[test]
235 pub fn test_message() {
236 assert_eq!(
237 message_to_string(&Message {
238 id: MessageId::Extended(0),
239 name: String::from("name"),
240 size: 0,
241 transmitter: Transmitter::VectorXXX,
242 signals: Vec::default()
243 }),
244 r#"BO_ 2147483648 name: 0 Vector__XXX"#
245 );
246 }
247
248 #[test]
249 pub fn test_nodes() {
250 assert_eq!(
251 nodes_to_string(&[Node(String::from("name"))]),
252 r#"BU_:
253 name"#
254 );
255 }
256}