andrew@home:~$

Macro for checking tuple of options

Today, I was programming and ran into a little issue. Before, I was using this macro (from here):

#[macro_export]
macro_rules! all_or_nothing {
    ($($opt:expr),*) => {{
        if false $(|| $opt.is_none())* {
            None
        } else {
            Some(($($opt.expect("should never fail"),)*))
        }
    }};
}

to check a tuple of options to see if they were all available. I used it as follows:

pub fn create_bind_group(
    pipeline: Option<Res<RaytracingPipeline>>,
    raytracing_image: Option<Res<RaytracingImage>>,
    uniforms: Option<Res<RaytracingUniforms>>,
    bvh: Option<Res<RaytracingBVH>>,
    tris: Option<Res<RaytracingTriangles>>,
    lights: Option<Res<RaytracingLights>>,
    image_collection: Option<Res<ImageCollection>>,
    textures: Option<Res<DisneyTextures>>,
    /* more parameters that are non-optional */
) {
    if let Some((
        pipeline,
        raytracing_image,
        uniforms,
        bvh,
        tris,
        lights,
        image_collection,
        textures,
    )) = all_or_nothing!(
        pipeline,
        raytracing_image,
        uniforms,
        bvh,
        tris,
        lights,
        image_collection,
        textures
    ) {
        /* 
            do things on a gpu
        */
    }
}

Note that all the types inside the options are different, so I can’t just iterate over a vector or array. I think I could box them and iterate over them as Box<dyn Option> or something similar but that sounded painful.

The problem is now I don’t know which variables are Some and which are None. So I wrote this little macro:

#[macro_export]
macro_rules! check_for_none {
    ($($var:ident),*) => {{
        $(
            if $var.is_none() {
                println!("{} is none", stringify!($var));
            }
        )*
    }};
}

and I can just use it as follows:

check_for_none!(
    pipeline,
    raytracing_image,
    uniforms,
    bvh,
    tris,
    lights,
    image_collection,
    textures
);

Decided I’d put this on the blog because I would need 15 reptuation to answer my own question on Stack Overflow (and I really don’t feel like having to appease a bunch of random people online just to have the “"”privilege””” of putting it on someone else’s website.)

Hopefully you find this useful!