diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/macros.rs | 188 |
2 files changed, 190 insertions, 0 deletions
@@ -19,6 +19,8 @@ extern crate cfg_if; #[cfg(test)] extern crate nix_test as nixtest; +#[macro_use] mod macros; + // In rust 1.8+ this should be `pub extern crate libc` but prior // to https://github.com/rust-lang/rust/issues/26775 being resolved // it is necessary to get a little creative. 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)* + } + }; +} |