rosrust/
rosmsg.rs
1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use ros_message::{Duration, Time};
3use std::collections::HashMap;
4use std::io;
5
6pub trait RosMsg: std::marker::Sized {
7 fn encode<W: io::Write>(&self, w: W) -> io::Result<()>;
8 fn decode<R: io::Read>(r: R) -> io::Result<Self>;
9
10 #[inline]
11 fn encode_vec(&self) -> io::Result<Vec<u8>> {
12 let mut writer = io::Cursor::new(Vec::with_capacity(128));
13 writer.set_position(4);
15
16 self.encode(&mut writer)?;
17
18 let message_length = (writer.position() - 4) as u32;
20 writer.set_position(0);
21 message_length.encode(&mut writer)?;
22 Ok(writer.into_inner())
23 }
24
25 #[inline]
26 fn decode_slice(bytes: &[u8]) -> io::Result<Self> {
27 let mut reader = io::Cursor::new(bytes);
28 reader.set_position(4);
30 Self::decode(&mut reader)
31 }
32}
33
34impl RosMsg for bool {
35 #[inline]
36 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
37 w.write_u8(*self as u8)
38 }
39
40 #[inline]
41 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
42 r.read_u8().map(|u| u > 0)
43 }
44}
45
46impl RosMsg for u8 {
47 #[inline]
48 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
49 w.write_u8(*self)
50 }
51
52 #[inline]
53 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
54 r.read_u8()
55 }
56}
57
58impl RosMsg for i8 {
59 #[inline]
60 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
61 w.write_i8(*self)
62 }
63
64 #[inline]
65 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
66 r.read_i8()
67 }
68}
69
70impl RosMsg for u16 {
71 #[inline]
72 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
73 w.write_u16::<LittleEndian>(*self)
74 }
75
76 #[inline]
77 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
78 r.read_u16::<LittleEndian>()
79 }
80}
81
82impl RosMsg for i16 {
83 #[inline]
84 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
85 w.write_i16::<LittleEndian>(*self)
86 }
87
88 #[inline]
89 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
90 r.read_i16::<LittleEndian>()
91 }
92}
93
94impl RosMsg for u32 {
95 #[inline]
96 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
97 w.write_u32::<LittleEndian>(*self)
98 }
99
100 #[inline]
101 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
102 r.read_u32::<LittleEndian>()
103 }
104}
105
106impl RosMsg for i32 {
107 #[inline]
108 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
109 w.write_i32::<LittleEndian>(*self)
110 }
111
112 #[inline]
113 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
114 r.read_i32::<LittleEndian>()
115 }
116}
117
118impl RosMsg for u64 {
119 #[inline]
120 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
121 w.write_u64::<LittleEndian>(*self)
122 }
123
124 #[inline]
125 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
126 r.read_u64::<LittleEndian>()
127 }
128}
129
130impl RosMsg for i64 {
131 #[inline]
132 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
133 w.write_i64::<LittleEndian>(*self)
134 }
135
136 #[inline]
137 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
138 r.read_i64::<LittleEndian>()
139 }
140}
141
142impl RosMsg for f32 {
143 #[inline]
144 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
145 w.write_f32::<LittleEndian>(*self)
146 }
147
148 #[inline]
149 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
150 r.read_f32::<LittleEndian>()
151 }
152}
153
154impl RosMsg for f64 {
155 #[inline]
156 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
157 w.write_f64::<LittleEndian>(*self)
158 }
159
160 #[inline]
161 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
162 r.read_f64::<LittleEndian>()
163 }
164}
165
166#[inline]
167pub fn encode_fixed_slice<W: io::Write, T: RosMsg>(data: &[T], mut w: W) -> io::Result<()> {
168 data.iter().try_for_each(|v| v.encode(w.by_ref()))
169}
170
171#[inline]
172pub fn decode_fixed_vec<R: io::Read, T: RosMsg>(len: u32, mut r: R) -> io::Result<Vec<T>> {
173 (0..len).map(move |_| T::decode(r.by_ref())).collect()
174}
175
176#[inline]
177pub fn encode_variable_slice<W: io::Write, T: RosMsg>(data: &[T], mut w: W) -> io::Result<()> {
178 (data.len() as u32).encode(w.by_ref())?;
179 encode_fixed_slice(data, w)
180}
181
182#[inline]
183pub fn decode_variable_vec<R: io::Read, T: RosMsg>(mut r: R) -> io::Result<Vec<T>> {
184 decode_fixed_vec(u32::decode(r.by_ref())?, r)
185}
186
187#[inline]
190#[cfg(target_endian = "little")]
191pub fn encode_variable_primitive_slice<W: io::Write, T: RosMsg>(
192 data: &[T],
193 mut w: W,
194) -> io::Result<()> {
195 (data.len() as u32).encode(w.by_ref())?;
196 let ptr = data.as_ptr() as *const u8;
197
198 w.write(unsafe { std::slice::from_raw_parts(ptr, data.len() * std::mem::size_of::<T>()) })
201 .map(|_| ())
202}
203
204#[inline]
205#[cfg(target_endian = "big")]
206pub fn encode_variable_primitive_slice<W: io::Write, T: RosMsg>(
207 data: &[T],
208 mut w: W,
209) -> io::Result<()> {
210 encode_variable_slice(data, w)
211}
212
213#[inline]
216#[cfg(target_endian = "little")]
217pub fn decode_variable_primitive_vec<R: io::Read, T: RosMsg>(mut r: R) -> io::Result<Vec<T>> {
218 let num_elements = u32::decode(r.by_ref())? as usize;
219 let num_bytes = num_elements * std::mem::size_of::<T>();
220
221 let mut buf = Vec::<T>::with_capacity(num_elements);
224
225 let buf_ptr = buf.as_mut_ptr();
226
227 let read_buf = unsafe { std::slice::from_raw_parts_mut(buf_ptr as *mut u8, num_bytes) };
229 r.read_exact(read_buf)?;
230
231 std::mem::forget(buf);
233
234 Ok(unsafe { Vec::from_raw_parts(buf_ptr, num_elements, num_elements) })
236}
237
238#[inline]
239#[cfg(target_endian = "big")]
240pub fn decode_variable_primitive_vec<R: io::Read, T: RosMsg>(mut r: R) -> io::Result<Vec<T>> {
241 decode_variable_vec(r)
242}
243
244#[inline]
245pub fn encode_str<W: io::Write>(value: &str, w: W) -> io::Result<()> {
246 encode_variable_slice(value.as_bytes(), w)
247}
248
249impl RosMsg for String {
250 #[inline]
251 fn encode<W: io::Write>(&self, w: W) -> io::Result<()> {
252 encode_str(self, w)
253 }
254
255 #[inline]
256 fn decode<R: io::Read>(r: R) -> io::Result<Self> {
257 decode_variable_vec::<R, u8>(r).and_then(|v| {
258 String::from_utf8(v).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
259 })
260 }
261}
262
263impl<Hasher> RosMsg for HashMap<String, String, Hasher>
264where
265 Hasher: std::hash::BuildHasher,
266 HashMap<String, String, Hasher>: Default,
267{
268 #[inline]
269 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
270 let rows = self
271 .iter()
272 .map(|(key, value)| format!("{}={}", key, value))
273 .collect::<Vec<String>>();
274 let data_size: usize = rows.iter().map(|item| item.len() + 4).sum();
275 write_data_size(data_size as u32, w.by_ref())?;
276 rows.into_iter()
277 .try_for_each(|item| item.encode(w.by_ref()))
278 }
279
280 #[inline]
281 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
282 let data_size = u64::from(read_data_size(r.by_ref())?);
283 let mut limited_r = r.take(data_size);
284 let mut output = HashMap::<String, String, Hasher>::default();
285 while let Ok(item) = String::decode(&mut limited_r) {
287 let parts = item.splitn(2, '=').collect::<Vec<&str>>();
288 match *parts.as_slice() {
289 [key, value] => output.insert(key.into(), value.into()),
290 _ => {
291 return Err(io::Error::new(
292 io::ErrorKind::InvalidData,
293 "Map rows need to have a format of key=value",
294 ));
295 }
296 };
297 }
298 Ok(output)
299 }
300}
301
302impl RosMsg for Time {
303 #[inline]
304 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
305 self.sec.encode(w.by_ref())?;
306 self.nsec.encode(w)?;
307 Ok(())
308 }
309
310 #[inline]
311 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
312 Ok(Self {
313 sec: RosMsg::decode(r.by_ref())?,
314 nsec: RosMsg::decode(r)?,
315 })
316 }
317}
318
319impl RosMsg for Duration {
320 #[inline]
321 fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
322 self.sec.encode(w.by_ref())?;
323 self.nsec.encode(w)?;
324 Ok(())
325 }
326
327 #[inline]
328 fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
329 Ok(Self {
330 sec: RosMsg::decode(r.by_ref())?,
331 nsec: RosMsg::decode(r)?,
332 })
333 }
334}
335
336#[inline]
337fn read_data_size<R: io::Read>(r: R) -> io::Result<u32> {
338 u32::decode(r)
339}
340
341#[inline]
342fn write_data_size<W: io::Write>(value: u32, w: W) -> io::Result<()> {
343 value.encode(w)
344}