1 // Copyright © 2015, Peter Atashian 2 // Licensed under the MIT License <LICENSE.md> 3 //! Macros to make things easier to define 4 macro_rules! DECLARE_HANDLE { 5 ($name:ident, $inner:ident) => { 6 #[allow(missing_copy_implementations)] pub enum $inner { } 7 pub type $name = *mut $inner; 8 }; 9 } 10 macro_rules! MAKE_HRESULT { 11 ($sev:expr, $fac:expr, $code:expr) => { 12 ($sev << 31) | ($fac << 16) | $code 13 } 14 } 15 macro_rules! MAKE_SCODE { 16 ($sev:expr, $fac:expr, $code:expr) => { 17 ($sev << 31) | ($fac << 16) | $code 18 } 19 } 20 macro_rules! HIDP_ERROR_CODES { 21 ($sev:expr, $code:expr) => { 22 ($sev << 28) | (::FACILITY_HID_ERROR_CODE << 16) | $code 23 } 24 } 25 macro_rules! MAKEFOURCC { 26 ($a:expr, $b:expr, $c:expr, $d:expr) => { 27 ($a as i32) | (($b as i32) << 8) | (($c as i32) << 16) | (($d as i32) << 24) 28 } 29 } 30 #[macro_export] 31 macro_rules! DEFINE_GUID { 32 ( 33 $name:ident, $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, 34 $b6:expr, $b7:expr, $b8:expr 35 ) => { 36 pub const $name: $crate::GUID = $crate::GUID { 37 Data1: $l, 38 Data2: $w1, 39 Data3: $w2, 40 Data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], 41 }; 42 } 43 } 44 macro_rules! CTL_CODE { 45 ($DeviceType:expr, $Function:expr, $Method:expr, $Access:expr) => { 46 ($DeviceType << 16) | ($Access << 14) | ($Function << 2) | $Method 47 } 48 } 49 macro_rules! HID_CTL_CODE { 50 ($id:expr) => { 51 CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_NEITHER, ::FILE_ANY_ACCESS) 52 } 53 } 54 macro_rules! HID_BUFFER_CTL_CODE { 55 ($id:expr) => { 56 CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_BUFFERED, ::FILE_ANY_ACCESS) 57 } 58 } 59 macro_rules! HID_IN_CTL_CODE { 60 ($id:expr) => { 61 CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_IN_DIRECT, ::FILE_ANY_ACCESS) 62 } 63 } 64 macro_rules! HID_OUT_CTL_CODE { 65 ($id:expr) => { 66 CTL_CODE!(::FILE_DEVICE_KEYBOARD, $id, ::METHOD_OUT_DIRECT, ::FILE_ANY_ACCESS) 67 } 68 } 69 macro_rules! AUDCLNT_ERR { 70 ($n:expr) => { 71 MAKE_HRESULT!(::SEVERITY_ERROR, ::FACILITY_AUDCLNT, $n) 72 }; 73 } 74 macro_rules! AUDCLNT_SUCCESS { 75 ($n:expr) => { 76 MAKE_SCODE!(::SEVERITY_SUCCESS, ::FACILITY_AUDCLNT, $n) 77 }; 78 } 79 macro_rules! BCRYPT_MAKE_INTERFACE_VERSION { 80 ($major:expr, $minor:expr) => { 81 ::BCRYPT_INTERFACE_VERSION { MajorVersion: $major, MinorVersion: $minor } 82 } 83 } 84 #[macro_export] 85 macro_rules! RIDL { 86 (interface $interface:ident ($vtbl:ident) 87 {$( 88 fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty 89 ),+} 90 ) => { 91 #[repr(C)] #[allow(missing_copy_implementations)] 92 pub struct $vtbl { 93 $(pub $method: unsafe extern "system" fn( 94 This: *mut $interface 95 $(,$p: $t)* 96 ) -> $rtr),+ 97 } 98 #[repr(C)] #[derive(Debug)] #[allow(missing_copy_implementations)] 99 pub struct $interface { 100 pub lpVtbl: *const $vtbl 101 } 102 impl $interface { 103 #[inline] 104 $(pub unsafe fn $method(&mut self $(,$p: $t)*) -> $rtr { 105 ((*self.lpVtbl).$method)(self $(,$p)*) 106 })+ 107 } 108 }; 109 (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) { 110 }) => { 111 #[repr(C)] #[allow(missing_copy_implementations)] 112 pub struct $vtbl { 113 pub parent: $crate::$pvtbl 114 } 115 #[repr(C)] #[derive(Debug)] #[allow(missing_copy_implementations)] 116 pub struct $interface { 117 pub lpVtbl: *const $vtbl 118 } 119 impl ::std::ops::Deref for $interface { 120 type Target = $crate::$pinterface; 121 #[inline] 122 fn deref(&self) -> &$crate::$pinterface { 123 unsafe { ::std::mem::transmute(self) } 124 } 125 } 126 impl ::std::ops::DerefMut for $interface { 127 #[inline] 128 fn deref_mut(&mut self) -> &mut $crate::$pinterface { 129 unsafe { ::std::mem::transmute(self) } 130 } 131 } 132 }; 133 (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) 134 {$( 135 fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty 136 ),+} 137 ) => { 138 #[repr(C)] #[allow(missing_copy_implementations)] 139 pub struct $vtbl { 140 pub parent: $crate::$pvtbl 141 $(,pub $method: unsafe extern "system" fn( 142 This: *mut $interface 143 $(,$p: $t)* 144 ) -> $rtr)+ 145 } 146 #[repr(C)] #[derive(Debug)] #[allow(missing_copy_implementations)] 147 pub struct $interface { 148 pub lpVtbl: *const $vtbl 149 } 150 impl $interface { 151 #[inline] 152 $(pub unsafe fn $method(&mut self $(,$p: $t)*) -> $rtr { 153 ((*self.lpVtbl).$method)(self $(,$p)*) 154 })+ 155 } 156 impl ::std::ops::Deref for $interface { 157 type Target = $crate::$pinterface; 158 #[inline] 159 fn deref(&self) -> &$crate::$pinterface { 160 unsafe { ::std::mem::transmute(self) } 161 } 162 } 163 impl ::std::ops::DerefMut for $interface { 164 #[inline] 165 fn deref_mut(&mut self) -> &mut $crate::$pinterface { 166 unsafe { ::std::mem::transmute(self) } 167 } 168 } 169 }; 170 } 171 macro_rules! UNION { 172 ($base:ident, $field:ident, $variant:ident, $variantmut:ident, $fieldtype:ty) => { 173 impl $base { 174 #[inline] 175 pub unsafe fn $variant(&self) -> &$fieldtype { 176 ::std::mem::transmute(&self.$field) 177 } 178 #[inline] 179 pub unsafe fn $variantmut(&mut self) -> &mut $fieldtype { 180 ::std::mem::transmute(&mut self.$field) 181 } 182 } 183 } 184 } 185 macro_rules! BITFIELD { 186 ($base:ident $field:ident: $fieldtype:ty [ 187 $($thing:ident $set_thing:ident[$r:expr],)+ 188 ]) => { 189 impl $base {$( 190 #[inline] 191 pub fn $thing(&self) -> $fieldtype { 192 let size = ::std::mem::size_of::<$fieldtype>() * 8; 193 self.$field << (size - $r.end) >> (size - $r.end + $r.start) 194 } 195 #[inline] 196 pub fn $set_thing(&mut self, val: $fieldtype) { 197 let mask = ((1 << ($r.end - $r.start)) - 1) << $r.start; 198 self.$field &= !mask; 199 self.$field |= (val << $r.start) & mask; 200 } 201 )+} 202 } 203 } 204 #[macro_export] 205 macro_rules! ENUM { 206 {enum $name:ident { $($variant:ident = $value:expr,)+ }} => { 207 #[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 208 pub struct $name(pub u32); 209 $(pub const $variant: $name = $name($value);)+ 210 }; 211 {enum $name:ident { $variant:ident = $value:expr, $($rest:tt)* }} => { 212 #[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 213 pub struct $name(pub u32); 214 pub const $variant: $name = $name($value); 215 ENUM!{@gen $name, $variant, $($rest)*} 216 }; 217 {enum $name:ident { $variant:ident, $($rest:tt)* }} => { 218 ENUM!{enum $name { $variant = 0, $($rest)* }} 219 }; 220 {@gen $name:ident, $base:ident,} => {}; 221 {@gen $name:ident, $base:ident, $variant:ident = $value:expr, $($rest:tt)*} => { 222 pub const $variant: $name = $name($value); 223 ENUM!{@gen $name, $variant, $($rest)*} 224 }; 225 {@gen $name:ident, $base:ident, $variant:ident, $($rest:tt)*} => { 226 pub const $variant: $name = $name($base.0 + 1u32); 227 ENUM!{@gen $name, $variant, $($rest)*} 228 }; 229 } 230 macro_rules! FLAGS { 231 {enum $name:ident { $($variant:ident = $value:expr,)+ }} => { 232 #[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 233 pub struct $name(pub u32); 234 $(pub const $variant: $name = $name($value);)+ 235 impl ::std::ops::BitAnd<$name> for $name { 236 type Output = $name; 237 fn bitand(self, o: $name) -> $name { $name(self.0 & o.0) } 238 } 239 impl ::std::ops::BitOr<$name> for $name { 240 type Output = $name; 241 fn bitor(self, o: $name) -> $name { $name(self.0 | o.0) } 242 } 243 impl ::std::ops::BitXor<$name> for $name { 244 type Output = $name; 245 fn bitxor(self, o: $name) -> $name { $name(self.0 ^ o.0) } 246 } 247 impl ::std::ops::Not for $name { 248 type Output = $name; 249 fn not(self) -> $name { $name(!self.0) } 250 } 251 } 252 } 253 macro_rules! STRUCT { 254 {$(#[$attrs:meta])* nodebug struct $name:ident { $($field:ident: $ftype:ty,)+ }} => { 255 #[repr(C)] $(#[$attrs])* 256 pub struct $name { 257 $(pub $field: $ftype,)+ 258 } 259 impl Copy for $name {} 260 impl Clone for $name { fn clone(&self) -> $name { *self } } 261 }; 262 {$(#[$attrs:meta])* struct $name:ident { $($field:ident: $ftype:ty,)+ }} => { 263 #[repr(C)] #[derive(Debug)] $(#[$attrs])* 264 pub struct $name { 265 $(pub $field: $ftype,)+ 266 } 267 impl Copy for $name {} 268 impl Clone for $name { fn clone(&self) -> $name { *self } } 269 }; 270 } 271