3 releases
Uses new Rust 2024
new 0.1.2 | Apr 15, 2025 |
---|---|
0.1.1 | Apr 15, 2025 |
0.1.0 | Apr 15, 2025 |
#311 in Debugging
248 downloads per month
11KB
assert_enum_variants!
A Rust macro that asserts that all variants of an enum are as provided in the macro invocation.
Example
use assert_enum_variants::assert_enum_variants;
#[allow(dead_code)]
pub enum MyEnum {
A,
B(u32),
C {
a: String,
b: u32,
},
}
// This will compile successfully
// because all variants of `MyEnum` are accounted for.
assert_enum_variants!(MyEnum, { A, B, C });
It will fail to compile if any of the variants are missing or if there are any extra variants.
Example of faliure due to missing variants
use assert_enum_variants::assert_enum_variants;
#[allow(dead_code)]
pub enum MyEnum {
A,
B(u32),
C {
a: String,
b: u32,
},
}
// This will fail to compile
// because the `C` variant is missing.
assert_enum_variants!(MyEnum, { A, B });
Example of failure due to extra variants
use assert_enum_variants::assert_enum_variants;
#[allow(dead_code)]
pub enum MyEnum {
A,
B(u32),
C {
a: String,
b: u32,
},
}
// This will fail to compile
// because the `D` variant is not present on `MyEnum`.
assert_enum_variants!(MyEnum, { A, B, C, D });
Reasons for using this macro
Let's say you're writing some code that needs to handle all variants of an enum but there could be a situation that none of the variants fits.
enum ResumeFileFormat {
Pdf,
Docx,
Doc,
}
// ...
impl ResumeFileFormat {
fn from_extension(ext: &str) -> Option<Self> {
use ResumeFileFormat::{Pdf, Docx, Doc};
let file_format: ResumeFileFormat = match ext {
"pdf" => Pdf,
"docx" => Docx,
"doc" => Doc,
_ => return None,
};
Some(file_format)
}
}
Notice that due to a wildcard pattern, the compiler will not warn you if you
add a new variant to the enum and forget to modify the from_extension
.
That is, unless you use the assert_enum_variants!
macro.
The following code will fail to compile if you add a new variant to the enum
and forget to modify the from_extension
function.
use assert_enum_variants::assert_enum_variants;
enum ResumeFileFormat {
Pdf,
Docx,
Doc,
Json,
}
// ...
impl ResumeFileFormat {
fn from_extension(ext: &str) -> Option<Self> {
use ResumeFileFormat::{Pdf, Docx, Doc};
// This will fail to compile because the `Json` variant is missing.
assert_enum_variants!(ResumeFileFormat, { Pdf, Docx, Doc });
let file_format: ResumeFileFormat = match ext {
"pdf" => Pdf,
"docx" => Docx,
"doc" => Doc,
_ => return None,
};
Some(file_format)
}
}
Note on verbosity
In the example with a wildcard pattern, it would be better to provide an attribute macro like #[exhaustive_with_fallback]
that would add the invocation of assert_enum_variants!
with the handled variants.
However,
- This would require a bit more work to implement (and I don't have time for that right now),
- This would require a procedural rather than a declarative macro,
- This would slow down compilation time considerably more than this macro,
Due to the above reasons, I welcome you to create a separate crate that would provide such an attribute macro.