summaryrefslogtreecommitdiff
path: root/src/macros.rs
diff options
context:
space:
mode:
authorKamal Marhubi <kamal@marhubi.com>2016-03-15 14:09:07 -0400
committerKamal Marhubi <kamal@marhubi.com>2016-03-16 11:59:03 -0400
commitb4c9f5bad14c3ce13edc2f72ef409e3397dc7f10 (patch)
treebcd42506096a22032749959509acc6b0fce4e4cc /src/macros.rs
parent97157b4863105032de21aad6982eb17dbd62c120 (diff)
downloadnix-b4c9f5bad14c3ce13edc2f72ef409e3397dc7f10.zip
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 https://github.com/nix-rust/nix/issues/264
Diffstat (limited to 'src/macros.rs')
-rw-r--r--src/macros.rs188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 00000000..e6d58b10
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,188 @@
+/// The `libc_bitflags!` macro helps with a common use case of defining bitflags with values from
+/// the libc crate. It is used the same way as the `bitflags!` macro, except that only the name of
+/// the flag value has to be given.
+///
+/// The `libc` crate must be in scope with the name `libc`.
+///
+/// # Example
+/// ```
+/// 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,
+/// }
+/// }
+/// ```
+macro_rules! libc_bitflags {
+ // (non-pub) Exit rule.
+ (@call_bitflags
+ {
+ name: $BitFlags:ident,
+ type: $T:ty,
+ attrs: [$($attrs:tt)*],
+ flags: [$($flags:tt)*],
+ }
+ ) => {
+ bitflags! {
+ $($attrs)*
+ flags $BitFlags: $T {
+ $($flags)*
+ }
+ }
+ };
+
+ // (pub) Exit rule.
+ (@call_bitflags
+ {
+ pub,
+ name: $BitFlags:ident,
+ type: $T:ty,
+ attrs: [$($attrs:tt)*],
+ flags: [$($flags:tt)*],
+ }
+ ) => {
+ bitflags! {
+ $($attrs)*
+ pub flags $BitFlags: $T {
+ $($flags)*
+ }
+ }
+ };
+
+ // (non-pub) Done accumulating.
+ (@accumulate_flags
+ {
+ name: $BitFlags:ident,
+ type: $T:ty,
+ attrs: $attrs:tt,
+ },
+ $flags:tt;
+ ) => {
+ libc_bitflags! {
+ @call_bitflags
+ {
+ name: $BitFlags,
+ type: $T,
+ attrs: $attrs,
+ flags: $flags,
+ }
+ }
+ };
+
+ // (pub) Done accumulating.
+ (@accumulate_flags
+ {
+ pub,
+ name: $BitFlags:ident,
+ type: $T:ty,
+ attrs: $attrs:tt,
+ },
+ $flags:tt;
+ ) => {
+ libc_bitflags! {
+ @call_bitflags
+ {
+ pub,
+ name: $BitFlags,
+ type: $T,
+ attrs: $attrs,
+ flags: $flags,
+ }
+ }
+ };
+
+ // Munch an attr.
+ (@accumulate_flags
+ $prefix:tt,
+ [$($flags:tt)*];
+ #[$attr:meta] $($tail:tt)*
+ ) => {
+ libc_bitflags! {
+ @accumulate_flags
+ $prefix,
+ [
+ $($flags)*
+ #[$attr]
+ ];
+ $($tail)*
+ }
+ };
+
+ // Munch last ident if not followed by a comma.
+ (@accumulate_flags
+ $prefix:tt,
+ [$($flags:tt)*];
+ $flag:ident
+ ) => {
+ libc_bitflags! {
+ @accumulate_flags
+ $prefix,
+ [
+ $($flags)*
+ const $flag = libc::$flag,
+ ];
+ }
+ };
+
+ // Munch an ident; covers terminating comma case.
+ (@accumulate_flags
+ $prefix:tt,
+ [$($flags:tt)*];
+ $flag:ident, $($tail:tt)*
+ ) => {
+ libc_bitflags! {
+ @accumulate_flags
+ $prefix,
+ [
+ $($flags)*
+ const $flag = libc::$flag,
+ ];
+ $($tail)*
+ }
+ };
+
+ // (non-pub) Entry rule.
+ (
+ $(#[$attr:meta])*
+ flags $BitFlags:ident: $T:ty {
+ $($vals:tt)*
+ }
+ ) => {
+ libc_bitflags! {
+ @accumulate_flags
+ {
+ name: $BitFlags,
+ type: $T,
+ attrs: [$(#[$attr])*],
+ },
+ [];
+ $($vals)*
+ }
+ };
+
+ // (pub) Entry rule.
+ (
+ $(#[$attr:meta])*
+ pub flags $BitFlags:ident: $T:ty {
+ $($vals:tt)*
+ }
+ ) => {
+ libc_bitflags! {
+ @accumulate_flags
+ {
+ pub,
+ name: $BitFlags,
+ type: $T,
+ attrs: [$(#[$attr])*],
+ },
+ [];
+ $($vals)*
+ }
+ };
+}