diff --git a/Cargo.toml b/Cargo.toml index 39a4793..ce0e35e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,11 @@ members = ["proc"] nightly = [] proc = ["proc_static_assertions"] +# These are used for doctests in assert_one_feature +feature-1 = [] +feature-2 = [] + +default = ["feature-1", "feature-2"] + [badges] maintenance = { status = "actively-maintained" } diff --git a/src/assert_one_feature.rs b/src/assert_one_feature.rs new file mode 100644 index 0000000..78e5154 --- /dev/null +++ b/src/assert_one_feature.rs @@ -0,0 +1,39 @@ +/// Asserts that exactly one feature of a set is enabled. +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// // Both feature-1 and feature-2 are set, so this fails +/// +/// assert_one_feature!("feature-1","foo","bar","feature-2"); +/// ``` +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// // None of these features are set, so this fails +/// +/// assert_one_feature!("foo", "bar", "baz"); +/// ``` +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// // Exactly one of these features ("feature-1") is set, so this is fine +/// +/// assert_one_feature!("foo", "bar", "baz", "qup", "feature-1"); +/// assert_one_feature!("foo", "bar", "baz", "qup", "feature-2"); +/// ``` +#[macro_export] +macro_rules! assert_one_feature { + () => {}; + ($($feature:literal),+) => { + #[cfg(not(any($( + feature = $feature, + )+)))] + compile_error!(concat!("Must have one of the following features: ", stringify!($($feature,)+))); + const _: () = { + $( + #[cfg(feature = $feature)] + const ASSERT_ONE_FEATURE:() = (); + )+ + }; + }; +} diff --git a/src/lib.rs b/src/lib.rs index aa7e227..374cf9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,6 +116,7 @@ mod assert_cfg; mod assert_fields; mod assert_impl; mod assert_obj_safe; +mod assert_one_feature; mod assert_size; mod assert_trait; mod assert_type;