Reputation: 16148
I wrote a very simple macro which should implement a wrapper for a C struct:
macro_rules! features{
($struct_name: ident, $from_type: ident, $($name: ident => $vk: ident,)+) => {
#[derive(Debug, Copy, Clone)]
pub struct $struct_name{
$(
pub $name: bool,
)+
}
impl $struct_name{
pub fn empty() -> $struct_name{
$struct_name{
$(
$name: false,
)+
}
}
pub fn subset(&self, other: &Self) -> bool{
$((!self.$name | other.$name))&&+
}
}
//TODO: Probably just impl From with a cast?
impl From<vk::$from_type> for $struct_name{
fn from(features: vk::$from_type) -> $struct_name {
$struct_name{
$(
$name: features.$vk != 0,
)+
}
}
}
impl From<$struct_name> for vk::$from_type {
fn from(features: $struct_name) -> vk::$from_type {
vk::$from_type{
$(
$vk: features.$name as u32,
)+
}
}
}
impl fmt::Display for $struct_name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
$(
if self.$name {
try!(writeln!(f, "{},", stringify!($name)));
}
)+
writeln!(f, "")
}
}
}
}
I use it like this:
features!{
Features,
PhysicalDeviceFeatures,
robust_buffer_access => robustBufferAccess,
full_draw_index_uint32 => fullDrawIndexUint32,
image_cube_array => imageCubeArray,
....
}
This works, but I had to make a very ugly hack $from_type: ident
and then I use vk::$from_type
inside the macro. What I really want to do is:
features!{
Features,
vk::PhysicalDeviceFeatures,
robust_buffer_access => robustBufferAccess,
full_draw_index_uint32 => fullDrawIndexUint32,
image_cube_array => imageCubeArray,
....
}
Then I can fully supply the type, instead of relying on the ident being inside a hard coded module vk::
.
The problem is that I can not do this with path
or ty
$from_type{..}
Error:
error: expected expression, found `PhysicalDeviceFeatures`
-->
|
38 | $from_type{
| ^^^^^^^^^^
and
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
--> /home/maik/projects/ashlib/ash/src/feature.rs:38:27
|
38 | $from_type{
|
What symbol does $from_type
need to be for this to work?
I created a shorter example to express the problem that I am having more clearly (Playground):
mod foo {
struct Foo{
i: i32
}
}
macro_rules! c_enum {
(
$name:ty
) => {
fn new() -> $name {
$name{
i: 42
}
}
}
}
c_enum!{
foo::Foo
}
fn main() {
}
Upvotes: 1
Views: 360
Reputation: 8244
I don't know why path
or ty
fails, I would file a bug against Rust. In the past I've worked around this by using the tt
specifier, which matches almost everything.
Upvotes: 1