Skip to content

Commit 4715dde

Browse files
committed
Auto merge of #315 - kamalmarhubi:libc-bitflags, r=posborne
Add libc_bitflags convenience macro We define many bitflags types with values from the libc crate. Currently these look like this: bitflags!{ flags ProtFlags: libc::c_int { const PROT_NONE = libc::PROT_NONE, const PROT_READ = libc::PROT_READ, const PROT_WRITE = libc::PROT_WRITE, const PROT_EXEC = libc::PROT_EXEC, #[cfg(any(target_os = "linux", target_os = "android"))] const PROT_GROWSDOWN = libc::PROT_GROWSDOWN, #[cfg(any(target_os = "linux", target_os = "android"))] const PROT_GROWSUP = libc::PROT_GROWSUP, } } There's some repetition which is tedious. With the new macro, the above can instead be written libc_bitflags!{ flags ProtFlags: libc::c_int { PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC, #[cfg(any(target_os = "linux", target_os = "android"))] PROT_GROWSDOWN, #[cfg(any(target_os = "linux", target_os = "android"))] PROT_GROWSUP, } } Thanks to Daniel Keep for the Little Book of Rust Macros, and for helping with this macro. Refs #264
2 parents 97157b4 + c9e5a15 commit 4715dde

File tree

4 files changed

+220
-10
lines changed

4 files changed

+220
-10
lines changed

CONVENTIONS.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,32 @@ When creating newtypes, we use Rust's `CamelCase` type naming convention.
3434

3535
## Bitflags
3636

37-
We represent sets of constants that are intended to be combined using bitwise
38-
operations as parameters to functions by types defined using the `bitflags!`
39-
macro from the [bitflags crate][bitflags].
37+
Many C functions have flags parameters that are combined from constants using
38+
bitwise operations. We represent the types of these parameters by types defined
39+
using our `libc_bitflags!` macro, which is a convenience wrapper around the
40+
`bitflags!` macro from the [bitflags crate][bitflags] that brings in the
41+
constant value from `libc`.
42+
4043
We name the type for a set of constants whose element's names start with `FOO_`
4144
`FooFlags`.
4245

46+
For example,
47+
48+
```rust
49+
libc_bitflags!{
50+
flags ProtFlags : libc::c_int {
51+
PROT_NONE,
52+
PROT_READ,
53+
PROT_WRITE,
54+
PROT_EXEC,
55+
#[cfg(any(target_os = "linux", target_os = "android"))]
56+
PROT_GROWSDOWN,
57+
#[cfg(any(target_os = "linux", target_os = "android"))]
58+
PROT_GROWSUP,
59+
}
60+
}
61+
```
62+
4363

4464
## Enumerations
4565

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ extern crate cfg_if;
1919
#[cfg(test)]
2020
extern crate nix_test as nixtest;
2121

22+
#[macro_use] mod macros;
23+
2224
// In rust 1.8+ this should be `pub extern crate libc` but prior
2325
// to https://github.com/rust-lang/rust/issues/26775 being resolved
2426
// it is necessary to get a little creative.

src/macros.rs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/// The `libc_bitflags!` macro helps with a common use case of defining bitflags with values from
2+
/// the libc crate. It is used the same way as the `bitflags!` macro, except that only the name of
3+
/// the flag value has to be given.
4+
///
5+
/// The `libc` crate must be in scope with the name `libc`.
6+
///
7+
/// # Example
8+
/// ```
9+
/// libc_bitflags!{
10+
/// flags ProtFlags: libc::c_int {
11+
/// PROT_NONE,
12+
/// PROT_READ,
13+
/// PROT_WRITE,
14+
/// PROT_EXEC,
15+
/// #[cfg(any(target_os = "linux", target_os = "android"))]
16+
/// PROT_GROWSDOWN,
17+
/// #[cfg(any(target_os = "linux", target_os = "android"))]
18+
/// PROT_GROWSUP,
19+
/// }
20+
/// }
21+
/// ```
22+
macro_rules! libc_bitflags {
23+
// (non-pub) Exit rule.
24+
(@call_bitflags
25+
{
26+
name: $BitFlags:ident,
27+
type: $T:ty,
28+
attrs: [$($attrs:tt)*],
29+
flags: [$($flags:tt)*],
30+
}
31+
) => {
32+
bitflags! {
33+
$($attrs)*
34+
flags $BitFlags: $T {
35+
$($flags)*
36+
}
37+
}
38+
};
39+
40+
// (pub) Exit rule.
41+
(@call_bitflags
42+
{
43+
pub,
44+
name: $BitFlags:ident,
45+
type: $T:ty,
46+
attrs: [$($attrs:tt)*],
47+
flags: [$($flags:tt)*],
48+
}
49+
) => {
50+
bitflags! {
51+
$($attrs)*
52+
pub flags $BitFlags: $T {
53+
$($flags)*
54+
}
55+
}
56+
};
57+
58+
// (non-pub) Done accumulating.
59+
(@accumulate_flags
60+
{
61+
name: $BitFlags:ident,
62+
type: $T:ty,
63+
attrs: $attrs:tt,
64+
},
65+
$flags:tt;
66+
) => {
67+
libc_bitflags! {
68+
@call_bitflags
69+
{
70+
name: $BitFlags,
71+
type: $T,
72+
attrs: $attrs,
73+
flags: $flags,
74+
}
75+
}
76+
};
77+
78+
// (pub) Done accumulating.
79+
(@accumulate_flags
80+
{
81+
pub,
82+
name: $BitFlags:ident,
83+
type: $T:ty,
84+
attrs: $attrs:tt,
85+
},
86+
$flags:tt;
87+
) => {
88+
libc_bitflags! {
89+
@call_bitflags
90+
{
91+
pub,
92+
name: $BitFlags,
93+
type: $T,
94+
attrs: $attrs,
95+
flags: $flags,
96+
}
97+
}
98+
};
99+
100+
// Munch an attr.
101+
(@accumulate_flags
102+
$prefix:tt,
103+
[$($flags:tt)*];
104+
#[$attr:meta] $($tail:tt)*
105+
) => {
106+
libc_bitflags! {
107+
@accumulate_flags
108+
$prefix,
109+
[
110+
$($flags)*
111+
#[$attr]
112+
];
113+
$($tail)*
114+
}
115+
};
116+
117+
// Munch last ident if not followed by a comma.
118+
(@accumulate_flags
119+
$prefix:tt,
120+
[$($flags:tt)*];
121+
$flag:ident
122+
) => {
123+
libc_bitflags! {
124+
@accumulate_flags
125+
$prefix,
126+
[
127+
$($flags)*
128+
const $flag = libc::$flag,
129+
];
130+
}
131+
};
132+
133+
// Munch an ident; covers terminating comma case.
134+
(@accumulate_flags
135+
$prefix:tt,
136+
[$($flags:tt)*];
137+
$flag:ident, $($tail:tt)*
138+
) => {
139+
libc_bitflags! {
140+
@accumulate_flags
141+
$prefix,
142+
[
143+
$($flags)*
144+
const $flag = libc::$flag,
145+
];
146+
$($tail)*
147+
}
148+
};
149+
150+
// (non-pub) Entry rule.
151+
(
152+
$(#[$attr:meta])*
153+
flags $BitFlags:ident: $T:ty {
154+
$($vals:tt)*
155+
}
156+
) => {
157+
libc_bitflags! {
158+
@accumulate_flags
159+
{
160+
name: $BitFlags,
161+
type: $T,
162+
attrs: [$(#[$attr])*],
163+
},
164+
[];
165+
$($vals)*
166+
}
167+
};
168+
169+
// (pub) Entry rule.
170+
(
171+
$(#[$attr:meta])*
172+
pub flags $BitFlags:ident: $T:ty {
173+
$($vals:tt)*
174+
}
175+
) => {
176+
libc_bitflags! {
177+
@accumulate_flags
178+
{
179+
pub,
180+
name: $BitFlags,
181+
type: $T,
182+
attrs: [$(#[$attr])*],
183+
},
184+
[];
185+
$($vals)*
186+
}
187+
};
188+
}

src/sys/mman.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ use std::os::unix::io::RawFd;
66

77
pub use self::consts::*;
88

9-
bitflags!{
9+
libc_bitflags!{
1010
flags ProtFlags : libc::c_int {
11-
const PROT_NONE = libc::PROT_NONE,
12-
const PROT_READ = libc::PROT_READ,
13-
const PROT_WRITE = libc::PROT_WRITE,
14-
const PROT_EXEC = libc::PROT_EXEC,
11+
PROT_NONE,
12+
PROT_READ,
13+
PROT_WRITE,
14+
PROT_EXEC,
1515
#[cfg(any(target_os = "linux", target_os = "android"))]
16-
const PROT_GROWSDOWN = libc::PROT_GROWSDOWN,
16+
PROT_GROWSDOWN,
1717
#[cfg(any(target_os = "linux", target_os = "android"))]
18-
const PROT_GROWSUP = libc::PROT_GROWSUP,
18+
PROT_GROWSUP,
1919
}
2020
}
2121

0 commit comments

Comments
 (0)