#[macro_export]
macro_rules! provided_attachments {
(@declare $getter_name:ident (single: $attachment_type:ty) -> $return_type:ty {
|$bind:ident| $transform:expr
}) => {
#[doc = concat!("Get attachment `", stringify!($getter_name), "` via type `", stringify!($attachment_type), "` from the error.")]
fn $getter_name(&self) -> $return_type;
};
(@implement $getter_name:ident (single: $attachment_type:ty) -> $return_type:ty {
|$bind:ident| $transform:expr
}) => {
fn $getter_name(&self) -> $return_type {
let $bind = Self::attachment::<$attachment_type>(self);
$transform
}
};
(@declare $getter_name:ident (multiple: $attachment_type:ty) -> $return_type:ty {
|$bind:ident| $transform:expr
}) => {
#[doc = concat!("Get attachment `", stringify!($getter_name), "` via type `", stringify!($attachment_type), "` from the error.")]
fn $getter_name(&self) -> $return_type;
};
(@implement $getter_name:ident (multiple: $attachment_type:ty) -> $return_type:ty {
|$bind:ident| $transform:expr
}) => {
fn $getter_name(&self) -> $return_type {
let $bind = Self::attachments::<$attachment_type>(self);
$transform
}
};
($(
$getter_name:ident ($multiplicity_matcher:ident : $attachment_type:ty) -> $return_type:ty { |$bind:ident| $transform:expr }
);* $(;)?) => {
#[doc = "Helper trait that is implemented for [`NeuErr`], which allows to comfortably retrieve typed context information."]
pub trait NeuErrAttachments {
$(
$crate::provided_attachments!(@declare $getter_name($multiplicity_matcher: $attachment_type) -> $return_type {
|$bind| $transform
});
)*
}
impl NeuErrAttachments for $crate::NeuErr {
$(
$crate::provided_attachments!(@implement $getter_name($multiplicity_matcher: $attachment_type) -> $return_type {
|$bind| $transform
});
)*
}
};
}
#[macro_export]
macro_rules! require_context {
(@async $($body:tt)* ) => {{
let call = async move || -> ::core::result::Result<_, $crate::NeuErr<$crate::ProvideContext>> { $($body)* };
call().await.map_err($crate::NeuErr::<$crate::ProvideContext>::remove_marker)
}};
(@sync $($body:tt)* ) => {{
let call = move || -> ::core::result::Result<_, $crate::NeuErr<$crate::ProvideContext>> { $($body)* };
call().map_err($crate::NeuErr::<$crate::ProvideContext>::remove_marker)
}};
(
$(#[$attrs:meta])*
$vis:vis async fn $name:ident
( $($params:tt)* ) -> $return:ty
$body:block
) => {
$(#[$attrs])*
$vis async fn $name
( $($params)* ) -> $return
{
$crate::require_context!(@async $body)
}
};
(
$(#[$attrs:meta])*
$vis:vis fn $name:ident
( $($params:tt)* ) -> $return:ty
$body:block
) => {
$(#[$attrs])*
$vis fn $name
( $($params)* ) -> $return
{
$crate::require_context!(@sync $body)
}
};
}
#[cfg(test)]
mod compile_tests {
#![allow(dead_code, reason = "Compile tests")]
use ::macro_rules_attribute::apply;
use crate::Result;
require_context!(
#[cfg(test)]
pub async fn test1(#[cfg(test)] _param: bool, (): ()) -> Result<()> {
Ok(())
}
);
#[apply(require_context)]
fn test2() -> Result<()> {
Ok(())
}
}