Skip to content

Instantly share code, notes, and snippets.

@tesaguri
Last active January 15, 2022 05:35
Show Gist options
  • Save tesaguri/2a1c0790a48bbda3dd7f71c26d02a793 to your computer and use it in GitHub Desktop.
Save tesaguri/2a1c0790a48bbda3dd7f71c26d02a793 to your computer and use it in GitHub Desktop.
A wrapper around `pin_project_lite::pin_project!` to handle `cfg` attributes on enum variants and fields. (cf. <https://github.com/taiki-e/pin-project-lite/issues/3>)
macro_rules! pin_project_cfg {
($(#[$($attr:tt)*])* $vis:vis enum $($rest:tt)+) => {
pin_project_cfg! {
@outer [$(#[$($attr)*])* $vis enum] $($rest)+
}
};
// Accumulate type parameters and `where` clause.
(@outer [$($accum:tt)*] $tt:tt $($rest:tt)+) => {
pin_project_cfg! {
@outer [$($accum)* $tt] $($rest)+
}
};
(@outer [$($accum:tt)*] { $($body:tt)* }) => {
pin_project_cfg! {
@body #[cfg(all())] [$($accum)*] {} $($body)*
}
};
// Process a variant with `cfg`.
(
@body
#[cfg(all($($pred_accum:tt)*))]
$outer:tt
{ $($accum:tt)* }
#[cfg($($pred:tt)*)]
$(#[$($attr:tt)*])* $variant:ident { $($body:tt)* },
$($rest:tt)*
) => {
// Create two versions of the enum with `cfg($pred)` and `cfg(not($pred))`.
pin_project_cfg! {
@variant_body
{ $($body)* }
{}
#[cfg(all($($pred_accum)* $($pred)*,))]
$outer
{ $($accum)* $(#[$($attr)*])* $variant }
$($rest)*
}
pin_project_cfg! {
@body
#[cfg(all($($pred_accum)* not($($pred)*),))]
$outer
{ $($accum)* }
$($rest)*
}
};
// Process a variant without `cfg`.
(
@body
#[cfg(all($($pred_accum:tt)*))]
$outer:tt
{ $($accum:tt)* }
$(#[$($attr:tt)*])* $variant:ident { $($body:tt)* },
$($rest:tt)*
) => {
pin_project_cfg! {
@variant_body
{ $($body)* }
{}
#[cfg(all($($pred_accum)*))]
$outer
{ $($accum)* $(#[$($attr)*])* $variant }
$($rest)*
}
};
// Process a variant field with `cfg`.
(
@variant_body
{
#[cfg($($pred:tt)*)]
$(#[$($attr:tt)*])* $field:ident: $ty:ty,
$($rest:tt)*
}
{ $($accum:tt)* }
#[cfg(all($($pred_accum:tt)*))]
$($outer:tt)*
) => {
pin_project_cfg! {
@variant_body
{$($rest)*}
{ $($accum)* $(#[$($attr)*])* $field: $ty, }
#[cfg(all($($pred_accum)* $($pred)*,))]
$($outer)*
}
pin_project_cfg! {
@variant_body
{ $($rest)* }
{ $($accum)* }
#[cfg(all($($pred_accum)* not($($pred)*),))]
$($outer)*
}
};
// Process a variant field without `cfg`.
(
@variant_body
{
$(#[$($attr:tt)*])* $field:ident: $ty:ty,
$($rest:tt)*
}
{ $($accum:tt)* }
$($outer:tt)*
) => {
pin_project_cfg! {
@variant_body
{$($rest)*}
{ $($accum)* $(#[$($attr)*])* $field: $ty, }
$($outer)*
}
};
(
@variant_body
{}
$body:tt
#[cfg(all($($pred_accum:tt)*))]
$outer:tt
{ $($accum:tt)* }
$($rest:tt)*
) => {
pin_project_cfg! {
@body
#[cfg(all($($pred_accum)*))]
$outer
{ $($accum)* $body, }
$($rest)*
}
};
(
@body
#[$cfg:meta]
[$($outer:tt)*]
$body:tt
) => {
#[$cfg]
pin_project_lite::pin_project! {
$($outer)* $body
}
};
}
pin_project_cfg! {
/// Doc
#[derive(Debug)]
pub enum E<T, U: Sized, V: 'static> {
A {
#[pin]
x: T,
y: U,
z: V,
},
#[cfg(feature = "foo")]
B {
x: (),
#[cfg(feature = "bar")]
#[pin]
y: T,
},
#[cfg(not(feature = "foo"))]
C {
x: (),
#[cfg(feature = "bar")]
y: (),
},
}
}
@tesaguri
Copy link
Author

tesaguri commented Feb 6, 2021

License of the code: CC0 1.0 Universal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment