#[macro_export]
macro_rules! builder_setter {
($(#[$meta:meta])* assign, $name:ident, $field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, $field: $ty) -> Self {
self.$field = $field;
self
}
};
($(#[$meta:meta])* assign, $name:ident, $holder:ident.$field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, $field: $ty) -> Self {
self.$holder.$field = $field;
self
}
};
($(#[$meta:meta])* into, $name:ident, $field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, $field: $ty) -> Self {
self.$field = $field.into();
self
}
};
($(#[$meta:meta])* into, $name:ident, $holder:ident.$field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, $field: $ty) -> Self {
self.$holder.$field = $field.into();
self
}
};
($(#[$meta:meta])* into_some, $name:ident, $field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, $field: $ty) -> Self {
self.$field = Some($field.into());
self
}
};
($(#[$meta:meta])* into_some, $name:ident, $holder:ident.$field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, $field: $ty) -> Self {
self.$holder.$field = Some($field.into());
self
}
};
($(#[$meta:meta])* push, $name:ident, $field:ident, $ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, value: $ty) -> Self {
self.$field.push(value.into());
self
}
};
($(#[$meta:meta])* insert, $name:ident, $field:ident, $key_ty:ty, $val_ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, key: $key_ty, value: $val_ty) -> Self {
self.$field.insert(key.into(), value.into());
self
}
};
($(#[$meta:meta])* insert, $name:ident, $holder:ident.$field:ident, $key_ty:ty, $val_ty:ty) => {
$(#[$meta])*
pub fn $name(mut self, key: $key_ty, value: $val_ty) -> Self {
self.$holder.$field.insert(key.into(), value.into());
self
}
};
($(#[$meta:meta])* predicate, $name:ident, $field:ident, $($bound:tt)+) => {
$(#[$meta])*
pub fn $name<F>(mut self, value: F) -> Self
where
F: $($bound)+,
{
self.$field = Some(Box::new(value));
self
}
};
($(#[$meta:meta])* duration_millis, $name:ident, $field:ident) => {
$(#[$meta])*
pub fn $name(mut self, duration: std::time::Duration) -> Self {
self.$field = Some(duration.as_millis() as u64);
self
}
};
($(#[$meta:meta])* clamp, $name:ident, $holder:ident.$field:ident, $min:expr, $max:expr) => {
$(#[$meta])*
pub fn $name(mut self, $field: f32) -> Self {
self.$holder.$field = $field.clamp($min, $max);
self
}
};
}
#[macro_export]
macro_rules! builder_build {
($(#[$meta:meta])* $node:ty) => {
$(#[$meta])*
pub fn build(self) -> anyhow::Result<$node> {
Ok(<$node>::new(self.config))
}
};
}
#[macro_export]
macro_rules! enum_str_method {
(
$(#[$meta:meta])*
$vis:vis fn $method:ident($enum:ident) -> $ret:ty {
$($variant:ident => $lit:literal),+ $(,)?
}
) => {
impl $enum {
$(#[$meta])*
$vis fn $method(&self) -> $ret {
match self {
$(Self::$variant => $lit,)+
}
}
}
};
}
#[macro_export]
macro_rules! enum_display_via_str {
($enum:ident { $($variant:ident => $lit:literal),+ $(,)? }) => {
impl std::fmt::Display for $enum {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
$(Self::$variant => $lit,)+
};
write!(f, "{s}")
}
}
};
}
#[macro_export]
macro_rules! debug_struct_fields {
($struct:ident { $($label:literal => $field:ident $(. $method:ident ( $($arg:expr),* $(,)? ))?),+ $(,)? }) => {
impl std::fmt::Debug for $struct {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(stringify!($struct))
$(.field($label, &self.$field $(. $method ( $($arg),* ))?))+
.finish()
}
}
};
}
#[macro_export]
macro_rules! default_struct_fields {
($struct:ident { $($field:ident: $value:expr),+ $(,)? }) => {
impl Default for $struct {
fn default() -> Self {
Self {
$($field: $value,)+
}
}
}
};
}
#[macro_export]
macro_rules! zeroed_count_init_body {
($count_field:ident, $config:ident, $($log_arg:tt)*) => {{
$crate::prelude::info!($($log_arg)*);
Ok(Self {
$count_field: 0,
$config,
})
}};
}
#[macro_export]
macro_rules! log_shutdown_fn_body {
($shutdown_msg:literal, $($final_log_arg:tt)*) => {{
$crate::prelude::info!($shutdown_msg);
$crate::prelude::info!($($final_log_arg)*);
Ok(())
}};
}
#[macro_export]
macro_rules! model_preflight {
($model:expr, $label:literal, [$($hint:expr),+ $(,)?]) => {
$crate::error::preflight_model_exists(
std::path::Path::new(&$model.path),
$label,
&[$($hint),+],
)
};
}
#[macro_export]
macro_rules! camera_image_decode_fn {
($vis:vis fn $name:ident($msg_ty:ty, $decoder_ty:ty) -> $ret:ty) => {
$vis fn $name(msg: $msg_ty, h264_decoder: $decoder_ty) -> $ret {
mecha10_camera_codec::decode_camera_image(&msg.format, &msg.image_bytes, msg.width, msg.height, h264_decoder)
}
};
}
#[macro_export]
macro_rules! odometry_publish_fn {
($odom_ty:ident, $topic:expr) => {
async fn publish_odometry(&self, ctx: &$crate::context::Context) -> $crate::error::Result<()> {
let odom = $odom_ty {
timestamp: $crate::prelude::now_micros(),
x: self.x,
y: self.y,
theta: self.theta,
linear_vel: self.cmd_linear,
angular_vel: self.cmd_angular,
};
ctx.publish_to($topic, &odom).await?;
Ok(())
}
};
}
#[macro_export]
macro_rules! new_with_defaults {
(
$(#[$meta:meta])*
$vis:vis fn new($($field:ident : $ty:ty),+ $(,)?) -> Self
) => {
$(#[$meta])*
$vis fn new($($field: $ty),+) -> Self {
Self {
$($field,)+
}
}
};
(
$(#[$meta:meta])*
$vis:vis fn new($($field:ident : $ty:ty),+ $(,)?) -> Self {
$($default_field:ident : $default_value:expr),+ $(,)?
}
) => {
$(#[$meta])*
$vis fn new($($field: $ty),+) -> Self {
Self {
$($field,)+
$($default_field: $default_value,)+
}
}
};
}
#[macro_export]
macro_rules! node_main {
($node_type:ty, $node_name:expr) => {
$crate::node_main!($node_type, $node_name, normal);
};
($node_type:ty, $node_name:expr, $health:ident) => {
$crate::register_node!($node_type);
pub async fn run() -> $crate::error::Result<()> {
let ctx = $crate::context::Context::new($node_name).await?;
let config: <$node_type as $crate::node::NodeImpl>::Config =
ctx.load_and_validate_node_config($node_name).await?;
$crate::node::run_node::<$node_type>(config, ctx, $crate::node::HealthReportingConfig::$health()).await
}
};
}
#[macro_export]
macro_rules! new_then_run_fn {
($node_type:ty) => {
pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
let node = <$node_type>::new().await?;
node.run().await?;
Ok(())
}
};
}