rosrust_codegen/
genmsg.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::error::{Result, ResultExt};
use crate::helpers;
use crate::helpers::MessageMap;
use crate::output_layout;
use ros_message::MessagePath;
use std::collections::{HashMap, HashSet};
use std::convert::TryInto;

pub fn depend_on_messages(
    ignore_bad_messages: bool,
    folders: &[&str],
    messages: &[&str],
) -> Result<output_layout::Layout> {
    let message_map = message_names_to_message_map(ignore_bad_messages, folders, messages)?;
    message_map_to_layout(&message_map)
}

fn message_names_to_message_map(
    ignore_bad_messages: bool,
    folders: &[&str],
    messages: &[&str],
) -> Result<MessageMap> {
    let message_pairs = messages
        .iter()
        .copied()
        .map(TryInto::try_into)
        .collect::<ros_message::Result<Vec<MessagePath>>>()
        .chain_err(|| "Failed to parse all message paths")?;
    helpers::get_message_map(ignore_bad_messages, folders, &message_pairs)
}

fn message_map_to_layout(message_map: &MessageMap) -> Result<output_layout::Layout> {
    let mut output = output_layout::Layout {
        packages: Vec::new(),
    };
    let hashes = helpers::calculate_md5(message_map)?;
    let packages = message_map
        .messages
        .keys()
        .map(|message| message.package().into())
        .chain(
            message_map
                .services
                .keys()
                .map(|message| message.package().into()),
        )
        .collect::<HashSet<String>>();
    for package in packages {
        let mut package_data = output_layout::Package {
            name: package.clone(),
            messages: Vec::new(),
            services: Vec::new(),
        };
        let names = message_map
            .messages
            .iter()
            .filter(|&(message, _value)| message.package() == package)
            .map(|(message, value)| (message.name().into(), value.0.source().into()))
            .collect::<HashMap<String, String>>();
        for (name, source) in names {
            let key = MessagePath::new(&package, name).chain_err(|| "Invalid message path")?;
            let message = message_map
                .messages
                .get(&key)
                .expect("Internal implementation contains mismatch in map keys")
                .clone();
            let md5sum = hashes
                .get(&key)
                .expect("Internal implementation contains mismatch in map keys")
                .clone();
            let msg_definition =
                helpers::generate_message_definition(&message_map.messages, &message)?;
            let msg_type = message.full_name();
            package_data.messages.push(output_layout::Message {
                message,
                msg_definition,
                msg_type,
                md5sum,
                source,
            });
        }
        let names = message_map
            .services
            .iter()
            .filter(|&(message, _value)| message.package() == package)
            .map(|(message, value)| (message.name().into(), value.source.clone()))
            .collect::<HashMap<String, String>>();
        for (name, source) in names {
            let md5sum = hashes
                .get(&MessagePath::new(&package, &name).chain_err(|| "Invalid message path")?)
                .expect("Internal implementation contains mismatch in map keys")
                .clone();
            let msg_type = format!("{}/{}", package, name);
            package_data.services.push(output_layout::Service {
                name,
                md5sum,
                msg_type,
                source,
            })
        }
        output.packages.push(package_data);
    }
    Ok(output)
}