blob: 0bbd6aabff7d46fe05213c8f31781c2dc3dc6495 [file] [log] [blame]
// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! Macros to make things easier to define
macro_rules! DECLARE_HANDLE {
($name:ident, $inner:ident) => {
#[allow(missing_copy_implementations)] pub enum $inner { }
pub type $name = *mut $inner;
};
}
macro_rules! MAKE_HRESULT {
($sev:expr, $fac:expr, $code:expr) => {
($sev << 31) | ($fac << 16) | $code
}
}
macro_rules! MAKE_SCODE {
($sev:expr, $fac:expr, $code:expr) => {
($sev << 31) | ($fac << 16) | $code
}
}
macro_rules! HIDP_ERROR_CODES {
($sev:expr, $code:expr) => {
($sev << 28) | (::FACILITY_HID_ERROR_CODE << 16) | $code
}
}
macro_rules! MAKEFOURCC {
($a:expr, $b:expr, $c:expr, $d:expr) => {
($a as i32) | (($b as i32) << 8) | (($c as i32) << 16) | (($d as i32) << 24)
}
}
#[macro_export]
macro_rules! DEFINE_GUID {
(
$name:ident, $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr,
$b6:expr, $b7:expr, $b8:expr
) => {
pub const $name: $crate::GUID = $crate::GUID {
Data1: $l,
Data2: $w1,
Data3: $w2,
Data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8],
};
}
}
macro_rules! CTL_CODE {
($DeviceType:expr, $Function:expr, $Method:expr, $Access:expr) => {
($DeviceType << 16) | ($Access << 14) | ($Function << 2) | $Method
}
}
macro_rules! HID_CTL_CODE {
($id:expr) => {
CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_NEITHER, ::FILE_ANY_ACCESS)
}
}
macro_rules! HID_BUFFER_CTL_CODE {
($id:expr) => {
CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_BUFFERED, ::FILE_ANY_ACCESS)
}
}
macro_rules! HID_IN_CTL_CODE {
($id:expr) => {
CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_IN_DIRECT, ::FILE_ANY_ACCESS)
}
}
macro_rules! HID_OUT_CTL_CODE {
($id:expr) => {
CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_OUT_DIRECT, ::FILE_ANY_ACCESS)
}
}
macro_rules! AUDCLNT_ERR {
($n:expr) => {
MAKE_HRESULT!(::SEVERITY_ERROR, ::FACILITY_AUDCLNT, $n)
};
}
macro_rules! AUDCLNT_SUCCESS {
($n:expr) => {
MAKE_SCODE!(::SEVERITY_SUCCESS, ::FACILITY_AUDCLNT, $n)
};
}
macro_rules! BCRYPT_MAKE_INTERFACE_VERSION {
($major:expr, $minor:expr) => {
::BCRYPT_INTERFACE_VERSION { MajorVersion: $major, MinorVersion: $minor }
}
}
#[macro_export]
macro_rules! RIDL {
(interface $interface:ident ($vtbl:ident)
{$(
fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
),+}
) => {
#[repr(C)] #[allow(missing_copy_implementations)]
pub struct $vtbl {
$(pub $method: unsafe extern "system" fn(
This: *mut $interface
$(,$p: $t)*
) -> $rtr),+
}
#[repr(C)] #[derive(Debug)] #[allow(missing_copy_implementations)]
pub struct $interface {
pub lpVtbl: *const $vtbl
}
impl $interface {
#[inline]
$(pub unsafe fn $method(&mut self $(,$p: $t)*) -> $rtr {
((*self.lpVtbl).$method)(self $(,$p)*)
})+
}
};
(interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {
}) => {
#[repr(C)] #[allow(missing_copy_implementations)]
pub struct $vtbl {
pub parent: $crate::$pvtbl
}
#[repr(C)] #[derive(Debug)] #[allow(missing_copy_implementations)]
pub struct $interface {
pub lpVtbl: *const $vtbl
}
impl ::std::ops::Deref for $interface {
type Target = $crate::$pinterface;
#[inline]
fn deref(&self) -> &$crate::$pinterface {
unsafe { ::std::mem::transmute(self) }
}
}
impl ::std::ops::DerefMut for $interface {
#[inline]
fn deref_mut(&mut self) -> &mut $crate::$pinterface {
unsafe { ::std::mem::transmute(self) }
}
}
};
(interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident)
{$(
fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
),+}
) => {
#[repr(C)] #[allow(missing_copy_implementations)]
pub struct $vtbl {
pub parent: $crate::$pvtbl
$(,pub $method: unsafe extern "system" fn(
This: *mut $interface
$(,$p: $t)*
) -> $rtr)+
}
#[repr(C)] #[derive(Debug)] #[allow(missing_copy_implementations)]
pub struct $interface {
pub lpVtbl: *const $vtbl
}
impl $interface {
#[inline]
$(pub unsafe fn $method(&mut self $(,$p: $t)*) -> $rtr {
((*self.lpVtbl).$method)(self $(,$p)*)
})+
}
impl ::std::ops::Deref for $interface {
type Target = $crate::$pinterface;
#[inline]
fn deref(&self) -> &$crate::$pinterface {
unsafe { ::std::mem::transmute(self) }
}
}
impl ::std::ops::DerefMut for $interface {
#[inline]
fn deref_mut(&mut self) -> &mut $crate::$pinterface {
unsafe { ::std::mem::transmute(self) }
}
}
};
}
macro_rules! UNION {
($base:ident, $field:ident, $variant:ident, $variantmut:ident, $fieldtype:ty) => {
impl $base {
#[inline]
pub unsafe fn $variant(&self) -> &$fieldtype {
::std::mem::transmute(&self.$field)
}
#[inline]
pub unsafe fn $variantmut(&mut self) -> &mut $fieldtype {
::std::mem::transmute(&mut self.$field)
}
}
}
}
macro_rules! BITFIELD {
($base:ident $field:ident: $fieldtype:ty [
$($thing:ident $set_thing:ident[$r:expr],)+
]) => {
impl $base {$(
#[inline]
pub fn $thing(&self) -> $fieldtype {
let size = ::std::mem::size_of::<$fieldtype>() * 8;
self.$field << (size - $r.end) >> (size - $r.end + $r.start)
}
#[inline]
pub fn $set_thing(&mut self, val: $fieldtype) {
let mask = ((1 << ($r.end - $r.start)) - 1) << $r.start;
self.$field &= !mask;
self.$field |= (val << $r.start) & mask;
}
)+}
}
}
#[macro_export]
macro_rules! ENUM {
{enum $name:ident { $($variant:ident = $value:expr,)+ }} => {
#[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct $name(pub u32);
$(pub const $variant: $name = $name($value);)+
};
{enum $name:ident { $variant:ident = $value:expr, $($rest:tt)* }} => {
#[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct $name(pub u32);
pub const $variant: $name = $name($value);
ENUM!{@gen $name, $variant, $($rest)*}
};
{enum $name:ident { $variant:ident, $($rest:tt)* }} => {
ENUM!{enum $name { $variant = 0, $($rest)* }}
};
{@gen $name:ident, $base:ident,} => {};
{@gen $name:ident, $base:ident, $variant:ident = $value:expr, $($rest:tt)*} => {
pub const $variant: $name = $name($value);
ENUM!{@gen $name, $variant, $($rest)*}
};
{@gen $name:ident, $base:ident, $variant:ident, $($rest:tt)*} => {
pub const $variant: $name = $name($base.0 + 1u32);
ENUM!{@gen $name, $variant, $($rest)*}
};
}
macro_rules! FLAGS {
{enum $name:ident { $($variant:ident = $value:expr,)+ }} => {
#[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct $name(pub u32);
$(pub const $variant: $name = $name($value);)+
impl ::std::ops::BitAnd<$name> for $name {
type Output = $name;
fn bitand(self, o: $name) -> $name { $name(self.0 & o.0) }
}
impl ::std::ops::BitOr<$name> for $name {
type Output = $name;
fn bitor(self, o: $name) -> $name { $name(self.0 | o.0) }
}
impl ::std::ops::BitXor<$name> for $name {
type Output = $name;
fn bitxor(self, o: $name) -> $name { $name(self.0 ^ o.0) }
}
impl ::std::ops::Not for $name {
type Output = $name;
fn not(self) -> $name { $name(!self.0) }
}
}
}
macro_rules! STRUCT {
{$(#[$attrs:meta])* nodebug struct $name:ident { $($field:ident: $ftype:ty,)+ }} => {
#[repr(C)] $(#[$attrs])*
pub struct $name {
$(pub $field: $ftype,)+
}
impl Copy for $name {}
impl Clone for $name { fn clone(&self) -> $name { *self } }
};
{$(#[$attrs:meta])* struct $name:ident { $($field:ident: $ftype:ty,)+ }} => {
#[repr(C)] #[derive(Debug)] $(#[$attrs])*
pub struct $name {
$(pub $field: $ftype,)+
}
impl Copy for $name {}
impl Clone for $name { fn clone(&self) -> $name { *self } }
};
}