bitvec/macros/
internal.rs

1#![doc(hidden)]
2#![doc = include_str!("../../doc/macros/internal.md")]
3
4//  Provide known mount-points of dependency crates.
5
6#[doc(hidden)]
7pub use core;
8
9#[doc(hidden)]
10pub use funty;
11
12#[doc(hidden)]
13#[macro_export]
14#[doc = include_str!("../../doc/macros/encode_bits.md")]
15macro_rules! __encode_bits {
16	/* ENTRY POINTS
17	 *
18	 * These arms match the syntax provided by the public macros, and dispatch
19	 * by storage type width.
20	 */
21
22	(u8, $ord:tt; $($val:expr),*) => {
23		$crate::__encode_bits!(u8 as u8, $ord; $($val),*)
24	};
25	(Cell<u8>, $ord:tt; $($val:expr),*) => {
26		$crate::__encode_bits!(Cell<u8> as u8, $ord; $($val),*)
27	};
28	(AtomicU8, $ord:tt; $($val:expr),*) => {
29		$crate::__encode_bits!(AtomicU8 as u8, $ord; $($val),*)
30	};
31	(RadiumU8, $ord:tt; $($val:expr),*) => {
32		$crate::__encode_bits!(RadiumU8 as u8, $ord; $($val),*)
33	};
34
35	(u16, $ord:tt; $($val:expr),*) => {
36		$crate::__encode_bits!(u16 as u16, $ord; $($val),*)
37	};
38	(Cell<u16>, $ord:tt; $($val:expr),*) => {
39		$crate::__encode_bits!(Cell<u16> as u16, $ord; $($val),*)
40	};
41	(AtomicU16, $ord:tt; $($val:expr),*) => {
42		$crate::__encode_bits!(AtomicU16 as u16, $ord; $($val),*)
43	};
44	(RadiumU16, $ord:tt; $($val:expr),*) => {
45		$crate::__encode_bits!(RadiumU16 as u16, $ord; $($val),*)
46	};
47
48	(u32, $ord:tt; $($val:expr),*) => {
49		$crate::__encode_bits!(u32 as u32, $ord; $($val),*)
50	};
51	(Cell<u32>, $ord:tt; $($val:expr),*) => {
52		$crate::__encode_bits!(Cell<u32> as u32, $ord; $($val),*)
53	};
54	(AtomicU32, $ord:tt; $($val:expr),*) => {
55		$crate::__encode_bits!(AtomicU32 as u32, $ord; $($val),*)
56	};
57	(RadiumU32, $ord:tt; $($val:expr),*) => {
58		$crate::__encode_bits!(RadiumU32 as u32, $ord; $($val),*)
59	};
60
61	(u64, $ord:tt; $($val:expr),*) => {
62		$crate::__encode_bits!(u64 as u64, $ord; $($val),*)
63	};
64	(Cell<u64>, $ord:tt; $($val:expr),*) => {
65		$crate::__encode_bits!(Cell<u64> as u64, $ord; $($val),*)
66	};
67	(AtomicU64, $ord:tt; $($val:expr),*) => {
68		$crate::__encode_bits!(AtomicU64 as u64, $ord; $($val),*)
69	};
70	(RadiumU64, $ord:tt; $($val:expr),*) => {
71		$crate::__encode_bits!(RadiumU64 as u64, $ord; $($val),*)
72	};
73
74	(usize, $ord:tt; $($val:expr),*) => {
75		$crate::__encode_bits!(usize as usize, $ord; $($val),*)
76	};
77	(Cell<usize>, $ord:tt; $($val:expr),*) => {
78		$crate::__encode_bits!(Cell<usize> as usize, $ord; $($val),*)
79	};
80	(AtomicUsize, $ord:tt; $($val:expr),*) => {
81		$crate::__encode_bits!(AtomicUsize as usize, $ord; $($val),*)
82	};
83	(RadiumUsize, $ord:tt; $($val:expr),*) => {
84		$crate::__encode_bits!(RadiumUsize as usize, $ord; $($val),*)
85	};
86
87	//  This arm routes `usize` into `u32` or `u64`, depending on target, and
88	//  marks them to return to `usize` after chunking.
89	($typ:ty as usize, $ord:tt; $($val:expr),*) => {{
90		const LEN: usize = $crate::__count_elts!(usize; $($val),*);
91
92		let out: [$typ; LEN];
93
94		#[cfg(target_pointer_width = "32")]
95		{
96			out = $crate::__encode_bits!($typ as u32 as usize, $ord; $($val),*);
97		}
98
99		#[cfg(target_pointer_width = "64")]
100		{
101			out = $crate::__encode_bits!($typ as u64 as usize, $ord; $($val),*);
102		}
103
104		out
105	}};
106
107	//  ZERO EXTENSION: Supply literal `0, ` tokens to ensure that elements can
108	//  be completely filled with bits.
109	($typ:ty as $uint:ident $(as $usz:ident)?, $ord:tt; $($val:expr),*) => {
110		$crate::__encode_bits!(
111			$typ as $uint $(as $usz)?, $ord; []; $($val,)*
112			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
113			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
114			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
115			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
116		)
117	};
118
119	/* EXIT POINT.
120	 *
121	 * This arm enters once the only remaining bit-expression tokens are the
122	 * literal `0, `s provided above. It does not enter while any opaque
123	 * user-provided bit expressions remain, and matching falls through to the
124	 * chunkers, below.
125	 *
126	 * Once entered, this converts each chunk of bit expressions into the
127	 * requested storage element, then emits an array of the encoded elements.
128	 * This array is the final value of the originally-invoked macro. The
129	 * invoker is responsible for turning the array into a `bitvec` type.
130	 */
131	(
132		$typ:ty as $uint:ident as usize, $ord:tt;
133		[$([$($bit:tt,)+],)*]; $(0,)*
134	) => {
135		[$($crate::__make_elem!($typ as $uint as usize, $ord; $($bit,)+),)*]
136	};
137	(
138		$typ:ty as $uint:ident, $ord:tt;
139		[$([$($bit:tt,)+],)*]; $(0,)*
140	) => {
141		[$($crate::__make_elem!($typ as $uint, $ord; $($bit,)+),)*]
142	};
143
144	/* CHUNKERS
145	 *
146	 * These arms munch through the token stream, creating a sequence of chunks
147	 * of bits. Each chunk contains bits to exactly fill one element, and gets
148	 * passed into `__make_elem!` for final encoding.
149	 */
150
151	(
152		$typ:ty as u8, $ord:tt; [$($elem:tt)*];
153		$a0:tt, $b0:tt, $c0:tt, $d0:tt, $e0:tt, $f0:tt, $g0:tt, $h0:tt,
154		$($t:tt)*
155	) => {
156		$crate::__encode_bits!(
157			$typ as u8, $ord; [$($elem)* [
158				$a0, $b0, $c0, $d0, $e0, $f0, $g0, $h0,
159			],]; $($t)*
160		)
161	};
162
163	(
164		$typ:ty as u16, $ord:tt; [$($elem:tt)*];
165		$a0:tt, $b0:tt, $c0:tt, $d0:tt, $e0:tt, $f0:tt, $g0:tt, $h0:tt,
166		$a1:tt, $b1:tt, $c1:tt, $d1:tt, $e1:tt, $f1:tt, $g1:tt, $h1:tt,
167		$($t:tt)*
168	) => {
169		$crate::__encode_bits!(
170			$typ as u16, $ord; [$($elem)* [
171				$a0, $b0, $c0, $d0, $e0, $f0, $g0, $h0,
172				$a1, $b1, $c1, $d1, $e1, $f1, $g1, $h1,
173			],]; $($t)*
174		)
175	};
176
177	(
178		$typ:ty as u32 $(as $usz:ident)?, $ord:tt; [$($elem:tt)*];
179		$a0:tt, $b0:tt, $c0:tt, $d0:tt, $e0:tt, $f0:tt, $g0:tt, $h0:tt,
180		$a1:tt, $b1:tt, $c1:tt, $d1:tt, $e1:tt, $f1:tt, $g1:tt, $h1:tt,
181		$a2:tt, $b2:tt, $c2:tt, $d2:tt, $e2:tt, $f2:tt, $g2:tt, $h2:tt,
182		$a3:tt, $b3:tt, $c3:tt, $d3:tt, $e3:tt, $f3:tt, $g3:tt, $h3:tt,
183		$($t:tt)*
184	) => {
185		$crate::__encode_bits!(
186			$typ as u32 $(as $usz)?, $ord; [$($elem)* [
187				$a0, $b0, $c0, $d0, $e0, $f0, $g0, $h0,
188				$a1, $b1, $c1, $d1, $e1, $f1, $g1, $h1,
189				$a2, $b2, $c2, $d2, $e2, $f2, $g2, $h2,
190				$a3, $b3, $c3, $d3, $e3, $f3, $g3, $h3,
191			],]; $($t)*
192		)
193	};
194
195	(
196		$typ:ty as u64 $(as $usz:ident)?, $ord:tt; [$($elem:tt)*];
197		$a0:tt, $b0:tt, $c0:tt, $d0:tt, $e0:tt, $f0:tt, $g0:tt, $h0:tt,
198		$a1:tt, $b1:tt, $c1:tt, $d1:tt, $e1:tt, $f1:tt, $g1:tt, $h1:tt,
199		$a2:tt, $b2:tt, $c2:tt, $d2:tt, $e2:tt, $f2:tt, $g2:tt, $h2:tt,
200		$a3:tt, $b3:tt, $c3:tt, $d3:tt, $e3:tt, $f3:tt, $g3:tt, $h3:tt,
201		$a4:tt, $b4:tt, $c4:tt, $d4:tt, $e4:tt, $f4:tt, $g4:tt, $h4:tt,
202		$a5:tt, $b5:tt, $c5:tt, $d5:tt, $e5:tt, $f5:tt, $g5:tt, $h5:tt,
203		$a6:tt, $b6:tt, $c6:tt, $d6:tt, $e6:tt, $f6:tt, $g6:tt, $h6:tt,
204		$a7:tt, $b7:tt, $c7:tt, $d7:tt, $e7:tt, $f7:tt, $g7:tt, $h7:tt,
205		$($t:tt)*
206	) => {
207		$crate::__encode_bits!(
208			$typ as u64 $(as $usz)?, $ord; [$($elem)* [
209				$a0, $b0, $c0, $d0, $e0, $f0, $g0, $h0,
210				$a1, $b1, $c1, $d1, $e1, $f1, $g1, $h1,
211				$a2, $b2, $c2, $d2, $e2, $f2, $g2, $h2,
212				$a3, $b3, $c3, $d3, $e3, $f3, $g3, $h3,
213				$a4, $b4, $c4, $d4, $e4, $f4, $g4, $h4,
214				$a5, $b5, $c5, $d5, $e5, $f5, $g5, $h5,
215				$a6, $b6, $c6, $d6, $e6, $f6, $g6, $h6,
216				$a7, $b7, $c7, $d7, $e7, $f7, $g7, $h7,
217			],]; $($t)*
218		)
219	};
220}
221
222/// Counts the number of expression tokens in a repetition sequence.
223#[doc(hidden)]
224#[macro_export]
225macro_rules! __count {
226	(@ $val:expr) => { 1 };
227	($($val:expr),* $(,)?) => {{
228		const LEN: usize = 0 $(+ $crate::__count!(@ $val))*;
229		LEN
230	}};
231}
232
233/// Counts the number of storage elements needed to store a bit sequence.
234#[doc(hidden)]
235#[macro_export]
236macro_rules! __count_elts {
237	($t:ty; $($val:expr),*) => {
238		$crate::mem::elts::<$t>($crate::__count!($($val),*))
239	};
240}
241
242#[doc(hidden)]
243#[macro_export]
244#[doc = include_str!("../../doc/macros/make_elem.md")]
245macro_rules! __make_elem {
246	//  Token-matching ordering names can use specialized work.
247	($typ:ty as $uint:ident $(as $usz:ident)?, Lsb0; $(
248		$a:expr, $b:expr, $c:expr, $d:expr,
249		$e:expr, $f:expr, $g:expr, $h:expr,
250	)*) => {{
251		const ELEM: $uint = $crate::__ty_from_bytes!(
252			$uint, Lsb0, [$($crate::macros::internal::u8_from_le_bits(
253				$a != 0, $b != 0, $c != 0, $d != 0,
254				$e != 0, $f != 0, $g != 0, $h != 0,
255			)),*]
256		);
257		$crate::mem::BitElement::<$typ>::new(ELEM $(as $usz)?).elem
258	}};
259	($typ:ty as $uint:ident $(as $usz:ident)?, Msb0; $(
260		$a:expr, $b:expr, $c:expr, $d:expr,
261		$e:expr, $f:expr, $g:expr, $h:expr,
262	)*) => {{
263		const ELEM: $uint = $crate::__ty_from_bytes!(
264			$uint, Msb0, [$($crate::macros::internal::u8_from_be_bits(
265				$a != 0, $b != 0, $c != 0, $d != 0,
266				$e != 0, $f != 0, $g != 0, $h != 0,
267			)),*]
268		);
269		$crate::mem::BitElement::<$typ>::new(ELEM $(as $usz)?).elem
270	}};
271	($typ:ty as $uint:ident $(as $usz:ident)?, LocalBits; $(
272		$a:expr, $b:expr, $c:expr, $d:expr,
273		$e:expr, $f:expr, $g:expr, $h:expr,
274	)*) => {{
275		const ELEM: $uint = $crate::__ty_from_bytes!(
276			$uint, LocalBits, [$($crate::macros::internal::u8_from_ne_bits(
277				$a != 0, $b != 0, $c != 0, $d != 0,
278				$e != 0, $f != 0, $g != 0, $h != 0,
279			)),*]
280		);
281		$crate::mem::BitElement::<$typ>::new(ELEM $(as $usz)?).elem
282	}};
283	//  Otherwise, invoke `BitOrder` for each bit and accumulate.
284	($typ:ty as $uint:ident $(as $usz:ident)?, $ord:tt; $($bit:expr),* $(,)?) => {{
285		let mut tmp: $uint = 0;
286		let _bits = $crate::slice::BitSlice::<$uint, $ord>::from_element_mut(
287			&mut tmp
288		);
289		let mut _idx = 0;
290		$( _bits.set(_idx, $bit != 0); _idx += 1; )*
291		$crate::mem::BitElement::<$typ>::new(tmp $(as $usz)?).elem
292	}};
293}
294
295/// Translates `false` into `0` and `true` into `!0`.
296#[doc(hidden)]
297#[macro_export]
298macro_rules! __extend_bool {
299	($val:expr, $typ:tt) => {{
300		type Mem = <$typ as $crate::store::BitStore>::Mem;
301		if $val != 0 {
302			<Mem as $crate::mem::BitRegister>::ALL
303		}
304		else {
305			<Mem as $crate::macros::internal::funty::Integral>::ZERO
306		}
307	}};
308}
309
310/// Constructs an unsigned integer from a list of *bytes*.
311#[doc(hidden)]
312#[macro_export]
313macro_rules! __ty_from_bytes {
314	(u8, Msb0, [$($byte:expr),*]) => {
315		u8::from_be_bytes([$($byte),*])
316	};
317	(u8, Lsb0, [$($byte:expr),*]) => {
318		u8::from_le_bytes([$($byte),*])
319	};
320	(u8, LocalBits, [$($byte:expr),*]) => {
321		u8::from_ne_bytes([$($byte),*])
322	};
323	(u16, Msb0, [$($byte:expr),*]) => {
324		u16::from_be_bytes([$($byte),*])
325	};
326	(u16, Lsb0, [$($byte:expr),*]) => {
327		u16::from_le_bytes([$($byte),*])
328	};
329	(u16, LocalBits, [$($byte:expr),*]) => {
330		u16::from_ne_bytes([$($byte),*])
331	};
332	(u32, Msb0, [$($byte:expr),*]) => {
333		u32::from_be_bytes([$($byte),*])
334	};
335	(u32, Lsb0, [$($byte:expr),*]) => {
336		u32::from_le_bytes([$($byte),*])
337	};
338	(u32, LocalBits, [$($byte:expr),*]) => {
339		u32::from_ne_bytes([$($byte),*])
340	};
341	(u64, Msb0, [$($byte:expr),*]) => {
342		u64::from_be_bytes([$($byte),*])
343	};
344	(u64, Lsb0, [$($byte:expr),*]) => {
345		u64::from_le_bytes([$($byte),*])
346	};
347	(u64, LocalBits, [$($byte:expr),*]) => {
348		u64::from_ne_bytes([$($byte),*])
349	};
350	(usize, Msb0, [$($byte:expr),*]) => {
351		usize::from_be_bytes([$($byte),*])
352	};
353	(usizeLsb0, , [$($byte:expr),*]) => {
354		usize::from_le_bytes([$($byte),*])
355	};
356	(usize, LocalBits, [$($byte:expr),*]) => {
357		usize::from_ne_bytes([$($byte),*])
358	};
359}
360
361/// Constructs a `u8` from bits applied in `Lsb0` order (`a` low, `h` high).
362#[doc(hidden)]
363#[inline(always)]
364#[cfg(not(tarpaulin_include))]
365pub const fn u8_from_le_bits(
366	a: bool,
367	b: bool,
368	c: bool,
369	d: bool,
370	e: bool,
371	f: bool,
372	g: bool,
373	h: bool,
374) -> u8 {
375	(a as u8)
376		| ((b as u8) << 1)
377		| ((c as u8) << 2)
378		| ((d as u8) << 3)
379		| ((e as u8) << 4)
380		| ((f as u8) << 5)
381		| ((g as u8) << 6)
382		| ((h as u8) << 7)
383}
384
385/// Constructs a `u8` from bits applied in `Msb0` order (`a` high, `h` low).
386#[doc(hidden)]
387#[inline(always)]
388#[cfg(not(tarpaulin_include))]
389pub const fn u8_from_be_bits(
390	a: bool,
391	b: bool,
392	c: bool,
393	d: bool,
394	e: bool,
395	f: bool,
396	g: bool,
397	h: bool,
398) -> u8 {
399	(h as u8)
400		| ((g as u8) << 1)
401		| ((f as u8) << 2)
402		| ((e as u8) << 3)
403		| ((d as u8) << 4)
404		| ((c as u8) << 5)
405		| ((b as u8) << 6)
406		| ((a as u8) << 7)
407}
408
409#[doc(hidden)]
410#[cfg(target_endian = "big")]
411pub use self::u8_from_be_bits as u8_from_ne_bits;
412#[doc(hidden)]
413#[cfg(target_endian = "little")]
414pub use self::u8_from_le_bits as u8_from_ne_bits;