dbc_gen/
lib.rs

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}