Last active
January 15, 2022 05:35
-
-
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>)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: (), | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
License of the code: CC0 1.0 Universal.