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