1pub mod builtin;
2pub mod sensor_msgs;
3pub mod std_msgs;
4
5use core::fmt::Display;
6use serde::Serialize;
7use serde::de::DeserializeOwned;
8use std::convert::From;
9
10#[macro_export]
12macro_rules! ros_type_name {
13 ($t:ty) => {{ std::any::type_name::<$t>().rsplit("::").next().unwrap() }};
14}
15
16pub trait RosMsgAdapter<'a>: Sized {
21 type Output: Serialize + for<'b> From<&'b Self>;
22
23 fn validate_ros_message(&self) -> Result<(), String> {
28 Ok(())
29 }
30
31 fn namespace() -> &'a str;
33
34 fn type_name() -> &'a str {
36 ros_type_name!(Self::Output)
37 }
38
39 fn type_hash() -> &'static str;
44}
45
46pub trait RosBridgeAdapter: Sized + 'static {
51 type RosMessage: Serialize + DeserializeOwned + 'static;
52
53 fn validate_ros_message(&self) -> Result<(), String> {
55 Ok(())
56 }
57
58 fn namespace() -> &'static str;
59
60 fn type_name() -> &'static str {
61 ros_type_name!(Self::RosMessage)
62 }
63
64 fn type_hash() -> &'static str;
65
66 fn to_ros_message(&self) -> Self::RosMessage;
67
68 fn from_ros_message(msg: Self::RosMessage) -> Result<Self, String>;
69}
70
71impl<T> RosBridgeAdapter for T
72where
73 T: RosMsgAdapter<'static> + TryFrom<<T as RosMsgAdapter<'static>>::Output> + 'static,
74 T::Output: Serialize + DeserializeOwned + 'static,
75 <T as TryFrom<<T as RosMsgAdapter<'static>>::Output>>::Error: Display,
76{
77 type RosMessage = <T as RosMsgAdapter<'static>>::Output;
78
79 fn validate_ros_message(&self) -> Result<(), String> {
80 <T as RosMsgAdapter<'static>>::validate_ros_message(self)
81 }
82
83 fn namespace() -> &'static str {
84 <T as RosMsgAdapter<'static>>::namespace()
85 }
86
87 fn type_name() -> &'static str {
88 <T as RosMsgAdapter<'static>>::type_name()
89 }
90
91 #[cfg(not(feature = "humble"))]
92 fn type_hash() -> &'static str {
93 <T as RosMsgAdapter<'static>>::type_hash()
94 }
95
96 #[cfg(feature = "humble")]
97 fn type_hash() -> &'static str {
98 "TypeHashNotSupported"
99 }
100
101 fn to_ros_message(&self) -> Self::RosMessage {
102 self.into()
103 }
104
105 fn from_ros_message(msg: Self::RosMessage) -> Result<Self, String> {
106 T::try_from(msg).map_err(|e| e.to_string())
107 }
108}