Skip to content

Commit 802cf70

Browse files
committed
cpubits: explicit WYSIWYG syntax
In #1398 I experimented with making some of the syntax implicit, but as soon as it became clear I also needed to add support for ignoring certain bit sizes and only running code on others that quickly became a bad idea. This commit changes the syntax to be fully explicit, like a `match` expression that takes an implicit argument of the number of bits with no other weird rules. If you want the block to appear in the code on e.g. 16-bit targets, they need to be explicitly named. This commit implements all permutations except for `16 | 32 | 64` since that amounts to no gating whatsoever, which defeats the point of using this crate.
1 parent 3a1f930 commit 802cf70

File tree

1 file changed

+70
-29
lines changed

1 file changed

+70
-29
lines changed

cpubits/src/lib.rs

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,27 @@
55
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
66
)]
77

8+
//! # Supported bit sizes
9+
//!
10+
//! This crate supports the following bit sizes:
11+
//! - `16`
12+
//! - `32`
13+
//! - `64`
14+
//!
15+
//! This matches the available options for `target_pointer_width` in `rustc`:
16+
//! ```text
17+
//! expected values for `target_pointer_width` are: `16`, `32`, and `64`
18+
//! ```
19+
//!
820
//! # Usage
921
//!
10-
//! Use this macro to e.g. conditionally define types at compile-time based on the word size.
22+
//! Use this macro to run code blocks specific to certain CPU word sizes, e.g. to conditionally
23+
//! define types at compile-time based on the word size.
24+
//!
25+
//! The macro doesn't create a new block and supports arbitrary statements in toplevel code, just
26+
//! like the `cfg-if` crate (whose guts it recycles).
27+
//!
28+
//! ## Basic usage
1129
//!
1230
//! ```
1331
//! cpubits::cpubits! {
@@ -17,6 +35,8 @@
1735
//! }
1836
//! ```
1937
//!
38+
//! ## Grouping multiple bit sizes
39+
//!
2040
//! If you would like to group together 16-bit and 32-bit platforms, you can do so as follows:
2141
//!
2242
//! ```
@@ -26,55 +46,76 @@
2646
//! }
2747
//! ```
2848
//!
29-
//! You can also use the shortened form of the above syntax which implicitly promotes 16-bit
30-
//! platforms to 32-bit ones:
49+
//! ## Handling single-size cases
50+
//!
51+
//! If you only want a block to run for a specific size, e.g. to know when it's possible to write
52+
//! `impl From<u64> for MyWordNewtype`, you can do the following:
3153
//!
3254
//! ```
55+
//! # type Word = u64;
56+
//! pub struct MyWordNewtype(Word);
57+
//!
3358
//! cpubits::cpubits! {
34-
//! 32 => { pub type Word = u32; }
35-
//! 64 => { pub type Word = u64; }
59+
//! 64 => {
60+
//! impl From<u64> for MyWordNewtype {
61+
//! #[inline]
62+
//! fn from(n: u64) -> MyWordNewtype {
63+
//! MyWordNewtype(n)
64+
//! }
65+
//! }
66+
//! }
3667
//! }
3768
//! ```
38-
//!
39-
//! 32-bit and 64-bit platforms can also be combined to differentiate them from 16-bit ones, e.g.
40-
//! `16 => { ... }, 32 | 64 => { ... }`, and `32 | 64` can be shortened to just `32` in such a case.
4169
4270
#[macro_export]
4371
macro_rules! cpubits {
44-
// Select between 16-bit and 32-bit, where 64-bit targets will use the 32-bit option
45-
(
46-
16 => { $( $tokens16:tt )* }
47-
32 => { $( $tokens32:tt )* }
48-
) => {
72+
// Only run the given block if we have selected a 16-bit word size, i.e. the code will be
73+
// ignored on 32-bit and 64-bit platforms.
74+
( 16 => { $( $tokens:tt )* } ) => {
4975
$crate::cpubits! {
50-
16 => { $( $tokens16 )* }
51-
32 | 64 => { $( $tokens32 )* }
76+
16 => { $( $tokens )* },
77+
32 | 64 => { }
5278
}
5379
};
5480

55-
// Only run the given block if we have selected the 64-bit backend, i.e. the code will be
81+
// Only run the given block if we have selected a 32-bit word size, i.e. the code will be
82+
// ignored on 32-bit and 64-bit platforms.
83+
( 32 => { $( $tokens:tt )* } ) => {
84+
$crate::cpubits! {
85+
16 => { }
86+
32 => { $( $tokens )* }
87+
64 => { }
88+
}
89+
};
90+
91+
// Only run the given block if we have selected a 64-bit word size, i.e. the code will be
5692
// ignored on 16-bit and 32-bit platforms.
57-
(
58-
64 => { $( $tokens64:tt )* }
59-
) => {
93+
( 64 => { $( $tokens:tt )* } ) => {
6094
$crate::cpubits! {
6195
16 | 32 => { }
62-
64 => { $( $tokens64 )* }
96+
64 => { $( $tokens )* }
6397
}
6498
};
6599

66-
// Select between 32-bit and 64-bit, where 16-bit targets will use the 32-bit option
67-
(
68-
32 => { $( $tokens32:tt )* }
69-
64 => { $( $tokens64:tt )* }
70-
) => {
100+
// Only run the block on 16-bit and 32-bit targets.
101+
( 16 | 32 => { $( $tokens:tt )* } ) => {
71102
$crate::cpubits! {
72-
16 | 32 => { $( $tokens32 )* }
73-
64 => { $( $tokens64 )* }
103+
16 => { $( $tokens )* }
104+
32 => { $( $tokens )* }
105+
64 => { }
106+
}
107+
};
108+
109+
// Only run the block on 32-bit and 64-bit targets.
110+
( 32 | 64 => { $( $tokens:tt )* } ) => {
111+
$crate::cpubits! {
112+
16 => { }
113+
32 => { $( $tokens )* }
114+
64 => { $( $tokens )* }
74115
}
75116
};
76117

77-
// Same as `16`/`32` above, but more explicit
118+
// Select between 16-bit and 32-bit options, where 64-bit will use the 32-bit option
78119
(
79120
16 => { $( $tokens16:tt )* }
80121
32 | 64 => { $( $tokens32:tt )* }
@@ -86,7 +127,7 @@ macro_rules! cpubits {
86127
}
87128
};
88129

89-
// Same as `32`/`64` above, but more explicit
130+
// Select between 32-bit and 64-bit options, where 16-bit will use the 32-bit option
90131
(
91132
16 | 32 => { $( $tokens32:tt )* }
92133
64 => { $( $tokens64:tt )* }

0 commit comments

Comments
 (0)