foundationdb_sys/lib.rs
1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4#![allow(clippy::unreadable_literal)]
5include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6
7/// Defines the FDB_API_VERSION constant and generates the `if_cfg_api_versions` macro
8/// from a list of (name, number) versions.
9///
10/// `if_cfg_api_versions` has one branch for all possible version combinations:
11/// - (min = ...)
12/// - (max = ...)
13/// - (min = ..., max = ...) with min < max
14///
15/// For macro expansion reasons, we need to generate all the branches in a single expansion,
16/// so this macro uses accumulators to gather all branch data before expanding it in one go.
17/// In short, this is a combinatorial generator. Given `[0, 1, 2, 3]` it generates branches for:
18/// - (min = 0)
19/// - (min = 1)
20/// - (min = 2)
21/// - (min = 3)
22/// - (max = 0)
23/// - (max = 1)
24/// - (max = 2)
25/// - (max = 3)
26/// - (min = 0, max = 1)
27/// - (min = 0, max = 2)
28/// - (min = 0, max = 3)
29/// - (min = 1, max = 2)
30/// - (min = 1, max = 3)
31/// - (min = 2, max = 3)
32macro_rules! versions_expand {
33 ($(($version_name:tt, $version:tt)),+ $(,)?) => {
34 // Entry point: start with a list of (version_name, version_number)
35 // define the FDB_API_VERSION constant
36 $(
37 #[cfg(feature = $version_name)]
38 pub const FDB_API_VERSION: u32 = $version;
39 )*
40 // Call the "@pre" phase with:
41 // - visited_versions: []
42 // - remaining_versions: versions
43 // - acc2: [] (will store min branches)
44 // - acc3: [] (will store max branches)
45 versions_expand!(@pre [][$(($version_name, $version))+][][]);
46 };
47 (@pre [$($max:tt)*][$min:tt $($other:tt)*][$(($($acc2:tt)*))*][$(($($acc3:tt)*))*]) => {
48 // "@pre" phase generates (min = ...) and (max = ...) branches
49 // While remaining_versions is not empty:
50 // - move one version from remaining to visited
51 // - add one "min" branch to acc2
52 // - add one "max" branch to acc3
53 versions_expand!(@pre [$($max)* $min][$($other)*][$(($($acc2)*))* ($min $($other)*)][$(($($acc3)*))* ($min $($max)*)]);
54 };
55 (@pre [$min:tt $($version:tt)*][] $acc2:tt $acc3:tt) => {
56 // remaining_versions is empty: end of "@pre" phase
57 // Call the "@mid" phase with:
58 // - min_range: [versions[0]]
59 // - max_range: versions[1..]
60 // - acc1: [] (will store min-max combination branches)
61 // - acc2: min_branches
62 // - acc3: max_branches
63 versions_expand!(@mid [$min][$($version)*][] $acc2 $acc3);
64 };
65 (@mid [$min:tt $($version:tt)*][$max:tt $($other:tt)*][$(($($acc1:tt)*))*] $acc2:tt $acc3:tt) => {
66 // "@mid" phase generates all (min = ..., max = ...) branches
67 // This step generates all pairs for the current min
68 // While the max_range is not empty:
69 // - let max be the smallest version in max_range
70 // - add the "min max" branch to acc1
71 // - move max to the min_range
72 versions_expand!(@mid [$min $($version)* $max][$($other)*][$(($($acc1)*))* ($min $max $($version)*)] $acc2 $acc3);
73 };
74 (@mid [$drop:tt $min:tt $($version:tt)*][] $acc1:tt $acc2:tt $acc3:tt) => {
75 // max_range is empty: end of inner "@mid" loop
76 // - drop current min
77 // - set the second smallest version in min_range as new min
78 // - set all remaining versions as the max_range
79 versions_expand!(@mid [$min][$($version)*] $acc1 $acc2 $acc3);
80 };
81 (@mid [$drop:tt][] $acc1:tt $acc2:tt $acc3:tt) => {
82 // min_range is empty: end of "@mid" phase
83 // Call the "@end" phase with:
84 // - the $ sign so it can use it as a symbol in the macro
85 // - acc1: min_max_branches
86 // - acc2: min_branches
87 // - acc3: max_branches
88 versions_expand!(@end ($) $acc1 $acc2 $acc3);
89 };
90 (@end ($d:tt)
91 [$((($min_name1:tt, $min1:tt) ($max_name1:tt, $max1:tt) $(($version_name1:tt, $version1:tt))*))*]
92 [$((($min_name2:tt, $min2:tt) $(($version_name2:tt, $version2:tt))*))*]
93 [$((($max_name3:tt, $max3:tt) $(($version_name3:tt, $version3:tt))*))*]
94 ) => {
95 // "@end" phase generates the macro in one expansion
96 // For each branch type, generates the appropriate cfg attributes
97
98 /// Similar to `cfg_api_versions` proc-macro, but as a regular macro.
99 /// Unlike proc-macros which are unstable on expressions and non-inlined modules,
100 /// `if_cfg_api_versions` can be used on these places.
101 ///
102 /// Any feature after the "min" and "max" arguments will be joined in the "any" predicate.
103 ///
104 /// ### Constraints:
105 /// - `if/else` always requires block syntax (i.e., `{}` around branches).
106 /// - Avoid using multiple items in a single macro call.
107 /// - Best suited for guarding expressions, single items, or blocks.
108 ///
109 /// ## Behavior
110 /// ### Single statement
111 /// Guard the statment without additional curly braces
112 /// ```rs
113 /// if_cfg_api_versions!(max = 520 => prinln!("foo"));
114 /// // expands to:
115 /// #[cfg(any(feature = "fdb-5_1", feature = "fdb-5_2"))]
116 /// println!("foo");
117 /// ```
118 ///
119 /// ### Muliple statements
120 /// Guard a block wrapping the statments
121 /// ```rs
122 /// if_cfg_api_versions!(max = 520 =>
123 /// prinln!("foo");
124 /// prinln!("bar");
125 /// );
126 /// // expands to:
127 /// #[cfg(any(feature = "fdb-5_1", feature = "fdb-5_2"))]
128 /// {
129 /// println!("foo");
130 /// println!("bar");
131 /// }
132 /// ```
133 ///
134 /// ### Single Item (e.g., `mod`, `fn`, etc.)
135 /// Guard the item without additional culry braces
136 /// ```rs
137 /// if_cfg_api_versions!(max = 520 => pub mod foo);
138 /// // expands to:
139 /// #[cfg(any(feature = "fdb-5_1", feature = "fdb-5_2"))]
140 /// pub mod foo;
141 /// ```
142 ///
143 /// ### Multiple Items: **NOT RECOMMANDED**
144 /// Only guard the first item (does not add curly braces since it would be invalid syntax)
145 /// ```rs
146 /// if_cfg_api_versions!(max = 520 =>
147 /// pub mod foo;
148 /// pub mod bar;
149 /// );
150 /// // expands to:
151 /// #[cfg(any(feature = "fdb-5_1", feature = "fdb-5_2"))]
152 /// pub mod foo;
153 /// pub mod bar; // not guarded
154 /// ```
155 ///
156 /// ### If/Else
157 /// Both branches must be wrapped in curly braces, guard the first branch and the second with the opposite condition
158 /// ```rs
159 /// let result = if_cfg_api_versions!(max = 520 => {
160 /// println!("5.x");
161 /// true
162 /// } else {
163 /// println!("6.0+");
164 /// false
165 /// });
166 /// // expands to:
167 /// let result = {
168 /// #[cfg(any(feature = "fdb-5_1", feature = "fdb-5_2"))]
169 /// {
170 /// println!("5.x");
171 /// true
172 /// }
173 /// #[cfg(not(any(feature = "fdb-5_1", feature = "fdb-5_2")))]
174 /// {
175 /// println!("6.0+");
176 /// false
177 /// }
178 /// };
179 /// ```
180 #[macro_export]
181 macro_rules! if_cfg_api_versions {
182 // multiple statements
183 ($d($k:tt = $v:tt),+ => $a:stmt; $d($b:stmt)+) => {
184 if_cfg_api_versions!($d($k=$v),+ => { $a; $d($b)+ })
185 };
186 // min-max branches
187 $(
188 (min=$min1, max=$max1 $d(,feature = $feature:literal)* => {$d($then:tt)*} else {$d($else:tt)*}) => {{
189 #[cfg(any(feature=$min_name1 $(,feature=$version_name1)* ,feature=$max_name1 $d(,feature=$feature)*))]
190 { $d($then)* }
191 #[cfg(not(any(feature=$min_name1 $(,feature=$version_name1)* ,feature=$max_name1 $d(,feature=$feature)*)))]
192 { $d($else)* }
193 }};
194 (min=$min1, max=$max1 $d(,feature = $feature:literal)* => $d($then:tt)*) => {
195 #[cfg(any(feature=$min_name1 $(,feature=$version_name1)* ,feature=$max_name1 $d(,feature=$feature)*))]
196 $d($then)*
197 };
198 )*
199 // min branches
200 $(
201 (min=$min2 $d(,feature = $feature:literal)* => {$d($then:tt)*} else {$d($else:tt)*}) => {{
202 #[cfg(any(feature=$min_name2 $(,feature=$version_name2)* $d(,feature=$feature)*))]
203 { $d($then)* }
204 #[cfg(not(any(feature=$min_name2 $(,feature=$version_name2)* $d(,feature=$feature)*)))]
205 { $d($else)* }
206 }};
207 (min=$min2 $d(,feature = $feature:literal)* => $d($then:tt)*) => {
208 #[cfg(any(feature=$min_name2 $(,feature=$version_name2)* $d(,feature=$feature)*))]
209 $d($then)*
210 };
211 )*
212 // max branches
213 $(
214 (max=$max3 $d(,feature = $feature:literal)* => {$d($then:tt)*} else {$d($else:tt)*}) => {{
215 #[cfg(any($(feature=$version_name3,)* feature=$max_name3 $d(,feature=$feature)*))]
216 { $d($then)* }
217 #[cfg(not(any($(feature=$version_name3,)* feature=$max_name3 $d(,feature=$feature)*)))]
218 { $d($else)* }
219 }};
220 (max=$max3 $d(,feature = $feature:literal)* => $d($then:tt)*) => {
221 #[cfg(any($(feature=$version_name3,)* feature=$max_name3 $d(,feature=$feature)*))]
222 $d($then)*
223 };
224 )*
225 // unsupported versions
226 (min=$min:tt, max=$max:tt $d(,feature = $feature:literal)* => $d($t:tt)*) => {
227 compile_error!(concat!("Use of unsupported version, or min >= max. Supported: ", $($min2, " " ,)*));
228 };
229 (min=$min:tt $d(,feature = $feature:literal)* => $d($t:tt)*) => {
230 compile_error!(concat!("Use of unsupported version. Supported: ", $($min2, " " ,)*));
231 };
232 (max=$max:tt $d(,feature = $feature:literal)* => $d($t:tt)*) => {
233 compile_error!(concat!("Use of unsupported version. Supported: ", $($min2, " " ,)*));
234 };
235 }
236 };
237}
238
239versions_expand![
240 ("fdb-5_1", 510),
241 ("fdb-5_2", 520),
242 ("fdb-6_0", 600),
243 ("fdb-6_1", 610),
244 ("fdb-6_2", 620),
245 ("fdb-6_3", 630),
246 ("fdb-7_0", 700),
247 ("fdb-7_1", 710),
248 ("fdb-7_3", 730),
249 ("fdb-7_4", 740),
250];