wasefire_one_of/lib.rs
1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Provides macros to check mutually exclusive features.
16
17#![no_std]
18
19/// Makes sure exactly one of the provided feature is enabled.
20///
21/// For example, `exactly_one_of!["a", "b", "c"]` will expand to:
22///
23/// ```ignore
24/// #[cfg(any(
25/// not(any(feature = "a", feature = "b", feature = "c")),
26/// all(feature = "a", feature = "b"),
27/// all(feature = "a", feature = "c"),
28/// all(feature = "b", feature = "c"),
29/// ))]
30/// compile_error!("Exactly one of feature \"a\", \"b\", or \"c\" can be enabled.");
31/// ```
32#[macro_export]
33macro_rules! exactly_one_of {
34 ($f:literal, $($fs:literal),+$(,)?) => {
35 $crate::internal_one_of!(0 [$f $($fs)*] "Exactly");
36 };
37}
38
39/// Makes sure at most one of the provided feature is enabled.
40///
41/// For example, `at_most_one_of!["a", "b", "c"]` will expand to:
42///
43/// ```ignore
44/// #[cfg(any(
45/// all(feature = "a", feature = "b"),
46/// all(feature = "a", feature = "c"),
47/// all(feature = "b", feature = "c"),
48/// ))]
49/// compile_error!("At most one of feature \"a\", \"b\", or \"c\" can be enabled.");
50/// ```
51#[macro_export]
52macro_rules! at_most_one_of {
53 ($f:literal, $($fs:literal),+$(,)?) => {
54 $crate::internal_one_of!(1 [$f $($fs)*] () ["At most";]);
55 };
56}
57
58#[doc(hidden)]
59#[macro_export]
60macro_rules! internal_one_of {
61 (0 [$($f:literal)*] $p:literal) => {
62 $crate::internal_one_of!(1 [$($f)*] (not(any($(feature = $f),*)),) [$p;]);
63 };
64
65 (1 [$f:literal $($fs:literal)*] $r:tt [$($ds:literal)*; $($d:literal)?]) => {
66 $crate::internal_one_of!(2 [$($fs)*] $f [$($fs)*] $r [$($ds)* $($d)?; $f]);
67 };
68 (1 [] $r:tt $ds:tt) => {
69 #[cfg(any $r)]
70 $crate::internal_one_of!(3 $ds);
71 };
72
73 (2 $s:tt $g:literal [$f:literal $($fs:literal)*] ($($r:tt)*) $d:tt) => {
74 $crate::internal_one_of!(2 $s $g [$($fs)*] ($($r)* all(feature = $g, feature = $f),) $d);
75 };
76 (2 $s:tt $g:literal [] $r:tt $d:tt) => {
77 $crate::internal_one_of!(1 $s $r $d);
78 };
79
80 (3 [$p:literal $a:literal; $b:literal]) => {
81 compile_error!(concat!($p, " one of feature ", stringify!($a), " or ", stringify!($b),
82 " can be enabled."));
83 };
84 (3 [$p:literal $($as:literal)*; $b:literal]) => {
85 compile_error!(concat!($p, " one of feature ",$(stringify!($as), ", ",)* "or ",
86 stringify!($b), " can be enabled."));
87 };
88}