rosrust_codegen/
genmsg.rs

1use crate::error::{Result, ResultExt};
2use crate::helpers;
3use crate::helpers::MessageMap;
4use crate::output_layout;
5use ros_message::MessagePath;
6use std::collections::{HashMap, HashSet};
7use std::convert::TryInto;
8
9pub fn depend_on_messages(
10    ignore_bad_messages: bool,
11    folders: &[&str],
12    messages: &[&str],
13) -> Result<output_layout::Layout> {
14    let message_map = message_names_to_message_map(ignore_bad_messages, folders, messages)?;
15    message_map_to_layout(&message_map)
16}
17
18fn message_names_to_message_map(
19    ignore_bad_messages: bool,
20    folders: &[&str],
21    messages: &[&str],
22) -> Result<MessageMap> {
23    let message_pairs = messages
24        .iter()
25        .copied()
26        .map(TryInto::try_into)
27        .collect::<ros_message::Result<Vec<MessagePath>>>()
28        .chain_err(|| "Failed to parse all message paths")?;
29    helpers::get_message_map(ignore_bad_messages, folders, &message_pairs)
30}
31
32fn message_map_to_layout(message_map: &MessageMap) -> Result<output_layout::Layout> {
33    let mut output = output_layout::Layout {
34        packages: Vec::new(),
35    };
36    let hashes = helpers::calculate_md5(message_map)?;
37    let packages = message_map
38        .messages
39        .keys()
40        .map(|message| message.package().into())
41        .chain(
42            message_map
43                .services
44                .keys()
45                .map(|message| message.package().into()),
46        )
47        .collect::<HashSet<String>>();
48    for package in packages {
49        let mut package_data = output_layout::Package {
50            name: package.clone(),
51            messages: Vec::new(),
52            services: Vec::new(),
53        };
54        let names = message_map
55            .messages
56            .iter()
57            .filter(|&(message, _value)| message.package() == package)
58            .map(|(message, value)| (message.name().into(), value.0.source().into()))
59            .collect::<HashMap<String, String>>();
60        for (name, source) in names {
61            let key = MessagePath::new(&package, name).chain_err(|| "Invalid message path")?;
62            let message = message_map
63                .messages
64                .get(&key)
65                .expect("Internal implementation contains mismatch in map keys")
66                .clone();
67            let md5sum = hashes
68                .get(&key)
69                .expect("Internal implementation contains mismatch in map keys")
70                .clone();
71            let msg_definition =
72                helpers::generate_message_definition(&message_map.messages, &message)?;
73            let msg_type = message.full_name();
74            package_data.messages.push(output_layout::Message {
75                message,
76                msg_definition,
77                msg_type,
78                md5sum,
79                source,
80            });
81        }
82        let names = message_map
83            .services
84            .iter()
85            .filter(|&(message, _value)| message.package() == package)
86            .map(|(message, value)| (message.name().into(), value.source.clone()))
87            .collect::<HashMap<String, String>>();
88        for (name, source) in names {
89            let md5sum = hashes
90                .get(&MessagePath::new(&package, &name).chain_err(|| "Invalid message path")?)
91                .expect("Internal implementation contains mismatch in map keys")
92                .clone();
93            let msg_type = format!("{}/{}", package, name);
94            package_data.services.push(output_layout::Service {
95                name,
96                md5sum,
97                msg_type,
98                source,
99            })
100        }
101        output.packages.push(package_data);
102    }
103    Ok(output)
104}