1#[macro_export]
6macro_rules! builder_setter {
7 ($(#[$meta:meta])* assign, $name:ident, $field:ident, $ty:ty) => {
8 $(#[$meta])*
9 pub fn $name(mut self, $field: $ty) -> Self {
10 self.$field = $field;
11 self
12 }
13 };
14 ($(#[$meta:meta])* assign, $name:ident, $holder:ident.$field:ident, $ty:ty) => {
15 $(#[$meta])*
16 pub fn $name(mut self, $field: $ty) -> Self {
17 self.$holder.$field = $field;
18 self
19 }
20 };
21 ($(#[$meta:meta])* into, $name:ident, $field:ident, $ty:ty) => {
22 $(#[$meta])*
23 pub fn $name(mut self, $field: $ty) -> Self {
24 self.$field = $field.into();
25 self
26 }
27 };
28 ($(#[$meta:meta])* into, $name:ident, $holder:ident.$field:ident, $ty:ty) => {
29 $(#[$meta])*
30 pub fn $name(mut self, $field: $ty) -> Self {
31 self.$holder.$field = $field.into();
32 self
33 }
34 };
35 ($(#[$meta:meta])* into_some, $name:ident, $field:ident, $ty:ty) => {
36 $(#[$meta])*
37 pub fn $name(mut self, $field: $ty) -> Self {
38 self.$field = Some($field.into());
39 self
40 }
41 };
42 ($(#[$meta:meta])* into_some, $name:ident, $holder:ident.$field:ident, $ty:ty) => {
43 $(#[$meta])*
44 pub fn $name(mut self, $field: $ty) -> Self {
45 self.$holder.$field = Some($field.into());
46 self
47 }
48 };
49 ($(#[$meta:meta])* push, $name:ident, $field:ident, $ty:ty) => {
50 $(#[$meta])*
51 pub fn $name(mut self, value: $ty) -> Self {
52 self.$field.push(value.into());
53 self
54 }
55 };
56 ($(#[$meta:meta])* insert, $name:ident, $field:ident, $key_ty:ty, $val_ty:ty) => {
57 $(#[$meta])*
58 pub fn $name(mut self, key: $key_ty, value: $val_ty) -> Self {
59 self.$field.insert(key.into(), value.into());
60 self
61 }
62 };
63 ($(#[$meta:meta])* insert, $name:ident, $holder:ident.$field:ident, $key_ty:ty, $val_ty:ty) => {
64 $(#[$meta])*
65 pub fn $name(mut self, key: $key_ty, value: $val_ty) -> Self {
66 self.$holder.$field.insert(key.into(), value.into());
67 self
68 }
69 };
70 ($(#[$meta:meta])* predicate, $name:ident, $field:ident, $($bound:tt)+) => {
71 $(#[$meta])*
72 pub fn $name<F>(mut self, value: F) -> Self
73 where
74 F: $($bound)+,
75 {
76 self.$field = Some(Box::new(value));
77 self
78 }
79 };
80 ($(#[$meta:meta])* duration_millis, $name:ident, $field:ident) => {
81 $(#[$meta])*
82 pub fn $name(mut self, duration: std::time::Duration) -> Self {
83 self.$field = Some(duration.as_millis() as u64);
84 self
85 }
86 };
87 ($(#[$meta:meta])* clamp, $name:ident, $holder:ident.$field:ident, $min:expr, $max:expr) => {
88 $(#[$meta])*
89 pub fn $name(mut self, $field: f32) -> Self {
90 self.$holder.$field = $field.clamp($min, $max);
91 self
92 }
93 };
94}
95
96#[macro_export]
97macro_rules! builder_build {
98 ($(#[$meta:meta])* $node:ty) => {
99 $(#[$meta])*
100 pub fn build(self) -> anyhow::Result<$node> {
101 Ok(<$node>::new(self.config))
102 }
103 };
104}
105
106#[macro_export]
107macro_rules! enum_str_method {
108 (
109 $(#[$meta:meta])*
110 $vis:vis fn $method:ident($enum:ident) -> $ret:ty {
111 $($variant:ident => $lit:literal),+ $(,)?
112 }
113 ) => {
114 impl $enum {
115 $(#[$meta])*
116 $vis fn $method(&self) -> $ret {
117 match self {
118 $(Self::$variant => $lit,)+
119 }
120 }
121 }
122 };
123}
124
125#[macro_export]
126macro_rules! enum_display_via_str {
127 ($enum:ident { $($variant:ident => $lit:literal),+ $(,)? }) => {
128 impl std::fmt::Display for $enum {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 let s = match self {
131 $(Self::$variant => $lit,)+
132 };
133 write!(f, "{s}")
134 }
135 }
136 };
137}
138
139#[macro_export]
140macro_rules! debug_struct_fields {
141 ($struct:ident { $($label:literal => $field:ident $(. $method:ident ( $($arg:expr),* $(,)? ))?),+ $(,)? }) => {
142 impl std::fmt::Debug for $struct {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 f.debug_struct(stringify!($struct))
145 $(.field($label, &self.$field $(. $method ( $($arg),* ))?))+
146 .finish()
147 }
148 }
149 };
150}
151
152#[macro_export]
153macro_rules! default_struct_fields {
154 ($struct:ident { $($field:ident: $value:expr),+ $(,)? }) => {
155 impl Default for $struct {
156 fn default() -> Self {
157 Self {
158 $($field: $value,)+
159 }
160 }
161 }
162 };
163}
164
165#[macro_export]
166macro_rules! zeroed_count_init_body {
167 ($count_field:ident, $config:ident, $($log_arg:tt)*) => {{
168 $crate::prelude::info!($($log_arg)*);
169 Ok(Self {
170 $count_field: 0,
171 $config,
172 })
173 }};
174}
175
176#[macro_export]
177macro_rules! log_shutdown_fn_body {
178 ($shutdown_msg:literal, $($final_log_arg:tt)*) => {{
179 $crate::prelude::info!($shutdown_msg);
180 $crate::prelude::info!($($final_log_arg)*);
181 Ok(())
182 }};
183}
184
185#[macro_export]
186macro_rules! model_preflight {
187 ($model:expr, $label:literal, [$($hint:expr),+ $(,)?]) => {
188 $crate::error::preflight_model_exists(
189 std::path::Path::new(&$model.path),
190 $label,
191 &[$($hint),+],
192 )
193 };
194}
195
196#[macro_export]
197macro_rules! camera_image_decode_fn {
198 ($vis:vis fn $name:ident($msg_ty:ty, $decoder_ty:ty) -> $ret:ty) => {
199 $vis fn $name(msg: $msg_ty, h264_decoder: $decoder_ty) -> $ret {
200 mecha10_camera_codec::decode_camera_image(&msg.format, &msg.image_bytes, msg.width, msg.height, h264_decoder)
201 }
202 };
203}
204
205#[macro_export]
206macro_rules! odometry_publish_fn {
207 ($odom_ty:ident, $topic:expr) => {
208 async fn publish_odometry(&self, ctx: &$crate::context::Context) -> $crate::error::Result<()> {
209 let odom = $odom_ty {
210 timestamp: $crate::prelude::now_micros(),
211 x: self.x,
212 y: self.y,
213 theta: self.theta,
214 linear_vel: self.cmd_linear,
215 angular_vel: self.cmd_angular,
216 };
217
218 ctx.publish_to($topic, &odom).await?;
219 Ok(())
220 }
221 };
222}
223
224#[macro_export]
225macro_rules! new_with_defaults {
226 (
227 $(#[$meta:meta])*
228 $vis:vis fn new($($field:ident : $ty:ty),+ $(,)?) -> Self
229 ) => {
230 $(#[$meta])*
231 $vis fn new($($field: $ty),+) -> Self {
232 Self {
233 $($field,)+
234 }
235 }
236 };
237 (
238 $(#[$meta:meta])*
239 $vis:vis fn new($($field:ident : $ty:ty),+ $(,)?) -> Self {
240 $($default_field:ident : $default_value:expr),+ $(,)?
241 }
242 ) => {
243 $(#[$meta])*
244 $vis fn new($($field: $ty),+) -> Self {
245 Self {
246 $($field,)+
247 $($default_field: $default_value,)+
248 }
249 }
250 };
251}
252
253#[macro_export]
254macro_rules! node_main {
255 ($node_type:ty, $node_name:expr) => {
256 $crate::node_main!($node_type, $node_name, normal);
257 };
258 ($node_type:ty, $node_name:expr, $health:ident) => {
259 $crate::register_node!($node_type);
263
264 pub async fn run() -> $crate::error::Result<()> {
265 let ctx = $crate::context::Context::new($node_name).await?;
266 let config: <$node_type as $crate::node::NodeImpl>::Config =
270 ctx.load_and_validate_node_config($node_name).await?;
271 $crate::node::run_node::<$node_type>(config, ctx, $crate::node::HealthReportingConfig::$health()).await
272 }
273 };
274}
275
276#[macro_export]
277macro_rules! new_then_run_fn {
278 ($node_type:ty) => {
279 pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
283 let node = <$node_type>::new().await?;
284 node.run().await?;
285 Ok(())
286 }
287 };
288}