rosrust_codegen/
output_layout.rs

1use crate::msg::Msg;
2use proc_macro2::Span;
3use quote::quote;
4use quote::ToTokens;
5use syn::Ident;
6
7pub struct Layout {
8    pub packages: Vec<Package>,
9}
10
11impl Layout {
12    pub fn token_stream<T: ToTokens>(&self, crate_prefix: &T) -> impl ToTokens {
13        let packages = self
14            .packages
15            .iter()
16            .map(|v| v.token_stream(crate_prefix))
17            .collect::<Vec<_>>();
18        quote! {
19            #(#packages)*
20        }
21    }
22}
23
24#[derive(Debug)]
25pub struct Package {
26    pub name: String,
27    pub messages: Vec<Message>,
28    pub services: Vec<Service>,
29}
30
31impl Package {
32    pub fn token_stream<T: ToTokens>(&self, crate_prefix: &T) -> impl ToTokens {
33        let name = Ident::new(&self.name, Span::call_site());
34        let messages = self
35            .messages
36            .iter()
37            .map(|v| v.token_stream(crate_prefix))
38            .collect::<Vec<_>>();
39        let services = self
40            .services
41            .iter()
42            .map(|v| v.token_stream(crate_prefix))
43            .collect::<Vec<_>>();
44        quote! {
45            pub mod #name {
46                #(#messages)*
47                #(#services)*
48            }
49        }
50    }
51}
52
53// TODO: Present source code of messages and services somehow
54
55#[derive(Debug)]
56pub struct Message {
57    pub message: Msg,
58    pub msg_definition: String,
59    pub md5sum: String,
60    pub msg_type: String,
61    pub source: String,
62}
63
64impl Message {
65    pub fn token_stream<T: ToTokens>(&self, crate_prefix: &T) -> impl ToTokens {
66        let Message {
67            message,
68            msg_definition,
69            md5sum,
70            msg_type,
71            source: _,
72        } = self;
73        let base_message = message.token_stream(crate_prefix);
74        let encode_message = message.token_stream_encode(crate_prefix);
75        let decode_message = message.token_stream_decode(crate_prefix);
76        let name = message.name_ident();
77        let header_tokens = message.header_token_stream(crate_prefix);
78        quote! {
79            #base_message
80
81            impl #crate_prefix Message for #name {
82                #[inline]
83                fn msg_definition() -> ::std::string::String {
84                    #msg_definition.into()
85                }
86
87                #[inline]
88                fn md5sum() -> ::std::string::String {
89                    #md5sum.into()
90                }
91
92                #[inline]
93                fn msg_type() -> ::std::string::String {
94                    #msg_type.into()
95                }
96
97                #header_tokens
98            }
99
100            impl #crate_prefix rosmsg::RosMsg for #name {
101                fn encode<W: ::std::io::Write>(&self, mut w: W) -> ::std::io::Result<()> {
102                    #encode_message
103                }
104
105                fn decode<R: ::std::io::Read>(mut r: R) -> ::std::io::Result<Self> {
106                    #decode_message
107                }
108            }
109        }
110    }
111}
112
113#[derive(Debug)]
114pub struct Service {
115    pub name: String,
116    pub md5sum: String,
117    pub msg_type: String,
118    pub source: String,
119}
120
121impl Service {
122    pub fn token_stream<T: ToTokens>(&self, crate_prefix: &T) -> impl ToTokens {
123        let Service {
124            name,
125            md5sum,
126            msg_type,
127            source: _,
128        } = self;
129        let name_ident = Ident::new(name, Span::call_site());
130        let req_ident = Ident::new(&format!("{}Req", name), Span::call_site());
131        let res_ident = Ident::new(&format!("{}Res", name), Span::call_site());
132
133        quote! {
134            #[allow(dead_code,non_camel_case_types,non_snake_case)]
135            #[derive(Clone, Debug, Default, PartialEq)]
136            pub struct #name_ident;
137
138            impl #crate_prefix Message for #name_ident {
139                #[inline]
140                fn msg_definition() -> ::std::string::String {
141                    String::new()
142                }
143
144                #[inline]
145                fn md5sum() -> ::std::string::String {
146                    #md5sum.into()
147                }
148
149                #[inline]
150                fn msg_type() -> ::std::string::String {
151                    #msg_type.into()
152                }
153            }
154
155            impl #crate_prefix rosmsg::RosMsg for #name_ident {
156                fn encode<W: ::std::io::Write>(&self, _w: W) -> ::std::io::Result<()> {
157                    Ok(())
158                }
159
160                fn decode<R: ::std::io::Read>(_r: R) -> ::std::io::Result<Self> {
161                    Ok(Self {})
162                }
163            }
164
165            impl #crate_prefix ServicePair for #name_ident {
166                type Request = #req_ident;
167                type Response = #res_ident;
168            }
169        }
170    }
171}