Skip to content

Instantly share code, notes, and snippets.

@mkatychev
Created September 7, 2024 23:04
`record!` macro
#[macro_export]
macro_rules! record {
($($fields:tt)+) => {
let fieldset = tracing::fieldset!($($fields)+);
$crate::valueset!(fieldset, $($fields)+);
};
}
#[macro_export]
macro_rules! valueset {
// === exit ===
(@ { $(,)* $($val:expr),* $(,)* }, $next:expr $(,)*) => {
let span = tracing::Span::current();
$(
let (__k, __v) = $val;
tracing::Span::current().record(*__k, __v);
)*
};
// Handle identity keys
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, debug(&$val)) },
$next,
$($rest)*
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$val)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, &$val) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, ?$($k:ident).+, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, debug(&$($k).+)) },
$next,
$($rest)*
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, %$($k:ident).+, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$($k).+)) },
$next,
$($rest)*
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = ?$val:expr) => {
$crate::valueset!(
@ { $($out),*, ($next, debug(&$val)) },
$next,
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = %$val:expr) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$val)) },
$next,
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, ?$($k:ident).+) => {
$crate::valueset!(
@ { $($out),*, ($next, debug(&$($k).+)) },
$next,
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, %$($k:ident).+) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$($k).+)) },
$next,
);
};
// Handle literal names
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = ?$val:expr, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, debug(&$val)) },
$next,
$($rest)*
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = %$val:expr, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$val)) },
$next,
$($rest)*
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = $val:expr, $($rest:tt)*) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$val)) },
$next,
$($rest)*
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = ?$val:expr) => {
$crate::valueset!(
@ { $($out),*, ($next, debug(&$val)) },
$next,
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = %$val:expr) => {
$crate::valueset!(
@ { $($out),*, ($next, display(&$val)) },
$next,
);
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = $val:expr) => {
$crate::valueset!(
@ { $($out),*, ($next, &$val) },
$next,
);
};
// Remainder is unparsable, but exists --- must be format args!
(@ { $(,)* $($out:expr),* }, $next:expr, $($rest:tt)+) => {
$crate::valueset!(@ { ($next, &format_args!($($rest)+)), $($out),* }, $next, );
};
// === entry ===
($fieldset: expr, $($fields:tt)+) => {
{
#[allow(unused_imports)]
use tracing::field::{debug, display, Value};
let mut iter = $fieldset.iter();
$crate::valueset!(
@ { },
iter.next().expect("FieldSet corrupted (this is a bug)"),
$($fields)+
);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment