bitvec/
macros.rs

1#![allow(deprecated)]
2#![doc = include_str!("../doc/macros.md")]
3
4#[macro_use]
5#[doc(hidden)]
6pub mod internal;
7
8mod tests;
9
10#[macro_export]
11#[doc = include_str!("../doc/macros/BitArr_type.md")]
12macro_rules! BitArr {
13	(for $len:expr, in $store:ty, $order:ty $(,)?) => {
14		$crate::array::BitArray::<
15			[$store; $crate::mem::elts::<$store>($len)], $order
16		>
17	};
18
19	(for $len:expr, in $store:ty $(,)?) => {
20		$crate::BitArr!(for $len, in $store, $crate::order::Lsb0)
21	};
22
23	(for $len:expr) => {
24		$crate::BitArr!(for $len, in usize)
25	};
26}
27
28#[macro_export]
29#[doc = include_str!("../doc/macros/bitarr_value.md")]
30macro_rules! bitarr {
31	/* `const`-expression constructors.
32	 *
33	 * These arms expand to expressions which are guaranteed to be valid in
34	 * `const` position: initializing `static` or `const`, or arguments to
35	 * `const fn`.
36	 *
37	 * > Other arms *may* be valid in `const`s, but do not guarantee it.
38	 *
39	 * They are more restricted than the general variants below, because the
40	 * trait system is not yet usable in `const` contexts and thus these
41	 * expansions can only use codepaths defined in this module, and cannot use
42	 * the rest of `bitvec`’s systems.
43	 *
44	 * All valid invocations with a leading `const` will remain valid if the
45	 * `const` is removed, though their expansion may change to no longer be
46	 * valid in `const` contexts.
47	 */
48
49	//  Bit-sequencing requires detecting `Cell` separately from other types.
50	//  See below.
51
52	(const Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
53		const ELTS: usize = $crate::__count_elts!($store; $($val),*);
54		type Data = [Cell<$store>; ELTS];
55		const DATA: Data = $crate::__encode_bits!(Cell<$store>, $order; $($val),*);
56
57		type This = $crate::array::BitArray<Data, $order>;
58		This { data: DATA, ..This::ZERO }
59	}};
60	(const $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
61		const ELTS: usize = $crate::__count_elts!($store; $($val),*);
62		type Data = [$store; ELTS];
63		const DATA: Data = $crate::__encode_bits!($store, $order; $($val),*);
64
65		type This = $crate::array::BitArray<Data, $order>;
66		This { data: DATA, ..This::ZERO }
67	}};
68
69	//  Bit-repetition is agnostic to types, so it only needs two arms.
70
71	(const $store:ty, $order:ty; $val:expr; $len:expr) => {{
72		use $crate::macros::internal::core;
73		type Mem = <$store as $crate::store::BitStore>::Mem;
74
75		const ELTS: usize = $crate::mem::elts::<$store>($len);
76		const ELEM: Mem = $crate::__extend_bool!($val, $store);
77		const DATA: [Mem; ELTS] = [ELEM; ELTS];
78
79		type This = $crate::array::BitArray<[$store; ELTS], $order>;
80		unsafe { core::mem::transmute::<_, This>(DATA) }
81	}};
82	(const $val:expr; $len:expr) => {{
83		$crate::bitarr!(const usize, $crate::order::Lsb0; $val; $len)
84	}};
85
86	(const $($val:expr),* $(,)?) => {{
87		$crate::bitarr!(const usize, Lsb0; $($val),*)
88	}};
89
90	/* Non-`const` constructors.
91	 *
92	 * These expansions are allowed to produce code that does not run in `const`
93	 * contexts. While it is *likely* that the expansions will be evaluated at
94	 * compile-time, they won’t do so while the `const` engine is active.
95	 */
96
97	/* Bit-sequence encoding.
98	 *
99	 * This requires four arms to the `const` section’s one, because of how both
100	 * the ordering and storage arguments may be provided. As macros operate
101	 * syntactically, before the type system begins, they have to accept any
102	 * syntax that could later be accepted as the name of a satisfying type.
103	 *
104	 * The `$order:ident` matcher uses the fact that `:ident` matches remain
105	 * matchable across deeper macro invocations, so that the bottom of the
106	 * macro stack can detect the magic tokens `LocalBits`, `Lsb0`, and `Msb0`,
107	 * and operate accordingly. The `$order:path` matcher is always opaque, and
108	 * serves as a fallback for complex type-names.
109	 *
110	 * `Cell<$store>` uses literal detection to extract the interior type width.
111	 * This cannot be done by `:ty` or `:path`, as these are opaque, and
112	 * `:ident` does not match `Cell<_>`.
113	 */
114
115	(Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
116		use $crate::macros::internal::core;
117		type Celled = core::cell::Cell<$store>;
118
119		const ELTS: usize = $crate::__count_elts!($store; $($val),*);
120		type Data = [Celled; ELTS];
121		type This = $crate::array::BitArray<Data, $order>;
122
123		This::new($crate::__encode_bits!(Cell<$store>, $order; $($val),*))
124	}};
125	(Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => {{
126		use $crate::macros::internal::core;
127		type Celled = core::cell::Cell<$store>;
128
129		const ELTS: usize = $crate::__count_elts!($store; $($val),*);
130		type This = $crate::array::BitArray<[Celled; ELTS], $order>;
131
132		This::new($crate::__encode_bits!(Cell<$store>, $order; $($val),*))
133	}};
134
135	($store:ident, $order:ident; $($val:expr),* $(,)?) => {{
136		const ELTS: usize = $crate::__count_elts!($store; $($val),*);
137		type This = $crate::array::BitArray<[$store; ELTS], $order>;
138
139		This::new($crate::__encode_bits!($store, $order; $($val),*))
140	}};
141	($store:ident, $order:path; $($val:expr),* $(,)?) => {{
142		const ELTS: usize = $crate::__count_elts!($store; $($val),*);
143		type This = $crate::array::BitArray<[$store; ELTS], $order>;
144
145		This::new($crate::__encode_bits!($store, $order; $($val),*))
146	}};
147
148
149	($store:ty, $order:ty; $val:expr; $len:expr) => {{
150		$crate::bitarr!(const $store, $order; $val; $len)
151	}};
152	($val:expr; $len:expr) => {{
153		$crate::bitarr!(const $val; $len)
154	}};
155	($($val:expr),* $(,)?) => {
156		$crate::bitarr!(usize, Lsb0; $($val),*)
157	};
158}
159
160#[macro_export]
161#[doc = include_str!("../doc/macros/bits.md")]
162macro_rules! bits {
163	/* `&'static` constructors.
164	 *
165	 * Like the `bitarr!(const …)` arms, these arms must expand to code that is
166	 * valid in `const` contexts. As such, they can only accept `$order`
167	 * arguments that are one of the `LocalBits`, `Lsb0`, or `Msb0` literals.
168	 * Once the underlying `static BitArray` is created,
169	 */
170	(static mut Cell<$store:ident>, $order:ty; $val:expr; $len:expr) => {{
171		use $crate::macros::internal::core;
172		type Celled = core::cell::Cell<$store>;
173		static mut DATA: $crate::BitArr!(for $len, in Celled, $order) =
174			$crate::bitarr!(const Cell<$store>, $order; $val; $len);
175		 &mut DATA[.. $len]
176	}};
177	(static mut $store:ident, $order:ident; $val:expr; $len:expr) => {{
178		static mut DATA: $crate::BitArr!(for $len, in $store, $order) =
179			$crate::bitarr!(const $store, $order; $val; $len);
180		DATA.get_unchecked_mut(.. $len)
181	}};
182
183	(static mut Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
184		use $crate::macros::internal::core;
185		type Celled = core::cell::Cell<$store>;
186		const BITS: usize = $crate::__count!($($val),*);
187
188		static mut DATA: $crate::BitArr!(for BITS, in $store, $order) =
189			$crate::bitarr!(const $store, $order; $($val),*);
190		&mut *(
191			DATA.get_unchecked_mut(.. BITS)
192				as *mut $crate::slice::BitSlice<$store, $order>
193				as *mut $crate::slice::BitSlice<Celled, $order>
194		)
195	}};
196	(static mut $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
197		const BITS: usize = $crate::__count!($($val),*);
198		static mut DATA: $crate::BitArr!(for BITS, in $store, $order) =
199			$crate::bitarr!(const $store, $order; $($val),*);
200		DATA.get_unchecked_mut(.. BITS)
201	}};
202
203	(static mut $val:expr; $len:expr) => {{
204		static mut DATA: $crate::BitArr!(for $len) =
205			$crate::bitarr!(const usize, $crate::order::Lsb0; $val; $len);
206		DATA.get_unchecked_mut(.. $len)
207	}};
208	(static mut $($val:expr),* $(,)?) => {{
209		$crate::bits!(static mut usize, Lsb0; $($val),*)
210	}};
211
212	(static Cell<$store:ident>, $order:ty; $val:expr; $len:expr) => {{
213		use $crate::macros::internal::core;
214		type Celled = core::cell::Cell<$store>;
215		static DATA: $crate::BitArr!(for $len, in $store, $order) =
216			$crate::bitarr!(const $store, $order; $val; $len);
217		unsafe {
218			&*(
219				DATA.get_unchecked(.. $len)
220					as *const $crate::slice::BitSlice<$store, $order>
221					as *const $crate::slice::BitSlice<Celled, $order>
222			)
223		}
224	}};
225	(static Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
226		use $crate::macros::internal::core;
227		type Celled = core::cell::Cell<$store>;
228		const BITS: usize = $crate::__count!($($val),*);
229
230		static DATA: $crate::BitArr!(for BITS, in $store, $order) =
231			$crate::bitarr!(const $store, $order; $($val),*);
232		unsafe {
233			&*(
234				DATA.get_unchecked(.. BITS)
235					as *const $crate::slice::BitSlice<$store, $order>
236					as *const $crate::slice::BitSlice<Celled, $order>
237			)
238		}
239	}};
240
241	(static $store:ident, $order:ident; $val:expr; $len:expr) => {{
242		static DATA: $crate::BitArr!(for $len, in $store, $order) =
243			$crate::bitarr!(const $store, $order; $val; $len);
244		unsafe { DATA.get_unchecked(.. $len) }
245	}};
246	(static $val:expr; $len:expr) => {{
247		static DATA: $crate::BitArr!(for $len) =
248			$crate::bitarr!(const usize, $crate::order::Lsb0; $val; $len);
249		unsafe { DATA.get_unchecked(.. $len) }
250	}};
251
252	(static $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
253		const BITS: usize = $crate::__count!($($val),*);
254		static DATA: $crate::BitArr!(for BITS, in $store, $order) =
255			$crate::bitarr!(const $store, $order; $($val),*);
256		unsafe { DATA.get_unchecked(.. BITS) }
257	}};
258	(static $($val:expr),* $(,)?) => {{
259		$crate::bits!(static usize, Lsb0; $($val),*)
260	}};
261
262	//  Repetition syntax `[bit ; count]`.
263	//  NOTE: `count` must be a `const`, as this is a non-allocating macro.
264
265	//  Sequence syntax `[bit (, bit)*]` or `[(bit ,)*]`.
266
267	//  Explicit order and store.
268
269	(mut Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
270		const BITS: usize = $crate::__count!($($val),*);
271		&mut $crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
272	}};
273	(mut Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => {{
274		const BITS: usize = $crate::__count!($($val),*);
275		&mut $crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
276	}};
277
278	(mut $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
279		const BITS: usize = $crate::__count!($($val),*);
280		&mut $crate::bitarr!($store, $order; $($val),*)[.. BITS]
281	}};
282	(mut $store:ident, $order:path; $($val:expr),* $(,)?) => {{
283		const BITS: usize = $crate::__count!($($val),*);
284		&mut $crate::bitarr!($store, $order; $($val),*)[.. BITS]
285	}};
286
287	//  Explicit order and store.
288	(mut $store:ty, $order:ty; $val:expr; $len:expr) => {{
289		&mut $crate::bitarr!($store, $order; $val; $len)[.. $len]
290	}};
291	//  Default order and store.
292	(mut $val:expr; $len:expr) => {
293		$crate::bits!(mut usize, $crate::order::Lsb0; $val; $len)
294	};
295
296	//  Default order and store.
297	(mut $($val:expr),* $(,)?) => {
298		$crate::bits!(mut usize, Lsb0; $($val),*)
299	};
300
301	//  Repeat everything from above, but now immutable.
302
303	($store:ty, $order:ty; $val:expr; $len:expr) => {{
304		&$crate::bitarr!($store, $order; $val; $len)[.. $len]
305	}};
306
307	(Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
308		const BITS: usize = $crate::__count!($($val),*);
309		&$crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
310	}};
311	($store:ident, $order:ident; $($val:expr),* $(,)?) => {{
312		const BITS: usize = $crate::__count!($($val),*);
313		&$crate::bitarr!($store, $order; $($val),*)[.. BITS]
314	}};
315
316	(Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => {{
317		const BITS: usize = $crate::__count!($($val),*);
318		&$crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
319	}};
320	($store:ident, $order:path; $($val:expr),* $(,)?) => {{
321		const BITS: usize = $crate::__count!($($val),*);
322		&$crate::bitarr!($store, $order; $($val),*)[.. BITS]
323	}};
324
325	//  Default order and store.
326	($val:expr; $len:expr) => {
327		$crate::bits!(usize, $crate::order::Lsb0; $val; $len)
328	};
329	($($val:expr),* $(,)?) => {
330		$crate::bits!(usize, Lsb0; $($val),*)
331	};
332}
333
334#[macro_export]
335#[cfg(feature = "alloc")]
336#[doc = include_str!("../doc/macros/bitvec.md")]
337macro_rules! bitvec {
338	//  First, capture the repetition syntax, as it is permitted to use runtime
339	//  values for the repetition count.
340	($store:ty, $order:ty; $val:expr; $len:expr) => {
341		$crate::vec::BitVec::<$store, $order>::repeat($val != 0, $len)
342	};
343	// Capture `Cell<T>` patterns and prevent them from being parsed as
344	// comparisons. Guess we didn't escape Most Vexing Parse after all.
345	(Cell<$store:ident>, $order:ident $($rest:tt)*) => {
346		$crate::vec::BitVec::from_bitslice($crate::bits!(Cell<$store>, $order $($rest)*))
347	};
348	($val:expr; $len:expr) => {
349		$crate::bitvec!(usize, $crate::order::Lsb0; $val; $len)
350	};
351
352	//  Delegate all others to the `bits!` macro.
353	($($arg:tt)*) => {
354		$crate::vec::BitVec::from_bitslice($crate::bits!($($arg)*))
355	};
356}
357
358#[macro_export]
359#[cfg(feature = "alloc")]
360#[doc = include_str!("../doc/macros/bitbox.md")]
361macro_rules! bitbox {
362	($($arg:tt)*) => {
363		$crate::bitvec!($($arg)*).into_boxed_bitslice()
364	};
365}