1#![no_std]
53
54pub use paste;
55
56#[macro_export]
57macro_rules! getfn {
58 () => {};
59 (
60 ($e:expr) $vis:vis $(extern $cc:literal)? fn $name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
61 $($tt:tt)*
62 ) => {
63 $crate::paste::item! {
64 #[allow(unused_parens)]
65 $vis fn [<getfn_ $name>]() -> ($(extern $cc)? fn($($argtype),*) $(-> $ret)?) { $e }
66 }
67
68 $crate::paste::item! {
69 $vis fn $name($($arg: $argtype),*) $(-> $ret)? {
70 [<getfn_ $name>]()($($arg),*)
71 }
72 }
73
74 $crate::getfn!($($tt)*);
75 };
76 (
77 ($e:expr) $vis:vis unsafe $(extern $cc:literal)? fn $name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
78 $($tt:tt)*
79 ) => {
80 $crate::paste::item! {
81 #[allow(unused_parens)]
82 $vis fn [<getfn_ $name>]() -> (unsafe $(extern $cc)? fn($($argtype),*) $(-> $ret)?) { $e }
83 }
84
85 $crate::paste::item! {
86 $vis unsafe fn $name($($arg: $argtype),*) $(-> $ret)? {
87 [<getfn_ $name>]()($($arg),*)
88 }
89 }
90
91 $crate::getfn!($($tt)*);
92 };
93 (
94 ($e:expr) $vis:vis $(extern $cc:literal)? fn Self::$name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
95 $($tt:tt)*
96 ) => {
97 $crate::paste::item! {
98 #[allow(unused_parens)]
99 $vis fn [<getfn_ $name>]() -> ($(extern $cc)? fn($($argtype),*) $(-> $ret)?) { $e }
100 }
101 $crate::paste::item! {
102 $vis fn $name($($arg: $argtype),*) $(-> $ret)? {
103 Self::[<getfn_ $name>]()($($arg),*)
104 }
105 }
106
107 $crate::getfn!($($tt)*);
108 };
109 (
110 ($e:expr) $vis:vis unsafe $(extern $cc:literal)? fn Self::$name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
111 $($tt:tt)*
112 ) => {
113 $crate::paste::item! {
114 #[allow(unused_parens)]
115 $vis fn [<getfn_ $name>]() -> (unsafe $(extern $cc)? fn($($argtype),*) $(-> $ret)?) { $e }
116 }
117 $crate::paste::item! {
118 $vis unsafe fn $name($($arg: $argtype),*) $(-> $ret)? {
119 Self::[<getfn_ $name>]()($($arg),*)
120 }
121 }
122
123 $crate::getfn!($($tt)*);
124 };
125 (
126 ($e:expr) $vis:vis $(extern $cc:literal)? fn Self::$name:ident([$($self:tt)+] $($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
127 $($tt:tt)*
128 ) => {
129 $crate::paste::item! {
130 #[allow(unused_parens)]
131 $vis fn [<getfn_ $name>]() -> ($crate::_getfn_ret!([$($self)+] $($cc)?, $($ret)?, $($argtype),*)) { $e }
132 }
133 $crate::paste::item! {
134 $vis fn $name($($self)+, $($arg: $argtype),*) $(-> $ret)? {
135 Self::[<getfn_ $name>]()($crate::_getfn_get_self_tok!($($self)+), $($arg),*)
136 }
137 }
138
139 $crate::getfn!($($tt)*);
140 };
141 (
142 ($e:expr) $vis:vis unsafe $(extern $cc:literal)? fn Self::$name:ident([$($self:tt)+] $($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
143 $($tt:tt)*
144 ) => {
145 $crate::paste::item! {
146 #[allow(unused_parens)]
147 $vis fn [<getfn_ $name>]() -> (unsafe $crate::_getfn_ret!([$($self)+] $($cc)?, $($ret)?, $($argtype),*)) { $e }
148 }
149 $crate::paste::item! {
150 $vis unsafe fn $name($($self)+, $($arg: $argtype),*) $(-> $ret)? {
151 Self::[<getfn_ $name>]()($crate::_getfn_get_self_tok!($($self)+), $($arg),*)
152 }
153 }
154
155 $crate::getfn!($($tt)*);
156 };
157}
158
159#[doc(hidden)]
160#[macro_export]
161macro_rules! _getfn_ret {
162 ([self] $($cc:literal)?, $($ret:ty)?, $($args:tt)*) => ($(extern $cc)? fn(Self, $($args),*) $(-> $ret)?);
163 ([& $($lt:lifetime)? self] $($cc:literal)?, $($ret:ty)?, $($args:tt)*) => ($(extern $cc)? fn(&$($lt)? Self, $($args),*) $(-> $ret)?);
164 ([& $($lt:lifetime)? mut self] $($cc:literal)?, $($ret:ty)?, $($args:tt)*) => ($(extern $cc)? fn(&$($lt)? mut Self, $($args),*) $(-> $ret)?);
165}
166
167#[doc(hidden)]
168#[macro_export]
169macro_rules! _getfn_get_self_tok {
170 (& $($lt:lifetime)? mut $t:tt) => ($t);
171 (& $($lt:lifetime)? $t:tt) => ($t);
172 ($t:tt) => ($t);
173}
174
175#[macro_export]
176macro_rules! alias {
177 ($name:ident) => ($crate::paste::expr!(crate:: [<__getfn_alias__ $name>] ::value()));
178}
179
180#[macro_export]
181macro_rules! def_alias {
182 () => {};
183 ($name:ident = $val:expr; $($tt:tt)*) => {
184 $crate::paste::item! {
185 pub(crate) mod [<__getfn_alias__ $name>] {
186 pub fn ___value___() -> *mut () {
187 use super::*;
188 $val
189 }
190 }
191 }
192 $crate::paste::item! {
193 use crate:: [<__getfn_alias__ $name>] as _;
194 }
195 };
196 ($name:ident: $t:ty = $val:expr; $($tt:tt)*) => {
197 $crate::paste::item! {
198 pub(crate) mod [<__getfn_alias__ $name>] {
199 pub fn ___value___() -> $t {
200 use super::*;
201 $val
202 }
203 }
204 }
205 $crate::paste::item! {
206 use crate:: [<__getfn_alias__ $name>] as _;
207 }
208 }
209}
210
211#[macro_export]
213macro_rules! get_addr {
214 ($custom:ident $($tt:tt)*) => {
215 $crate::_get_addr0!(
216 ($crate::alias!($custom))
217 $($tt)*
218 )
219 };
220
221 (($e:expr) $($tt:tt)*) => {
222 $crate::_get_addr0!(
223 ($e)
224 $($tt)*
225 )
226 };
227
228 ($module:literal $($tt:tt)*) => {
229 $crate::_get_addr0!(
230 (crate::__getfn_winapi__::um::libloaderapi::GetModuleHandleA(concat!($module, "\0").as_ptr() as _).cast::<()>())
231 $($tt)*
232 )
233 };
234}
235
236#[doc(hidden)]
237#[macro_export]
238macro_rules! _get_addr0 {
239 (($v:expr)) => ($v);
240 (($v:expr) @ $sym:literal $($tt:tt)*) => {
241 $crate::_get_addr0!(
242 (::core::mem::transmute::<_, *mut ()>(crate::__getfn_winapi__::um::libloaderapi::GetProcAddress($v as *mut _, concat!($sym, "\0").as_ptr() as _)))
243 $($tt)*
244 )
245 };
246 (($v:expr) * $($tt:tt)*) => {
247 $crate::_get_addr0!(
248 (($v as *mut *mut ()).read())
249 $($tt)*
250 )
251 };
252 (($v:expr) + $e:literal $($tt:tt)*) => {
253 $crate::_get_addr0!(
254 ($v.cast::<u8>().offset($e as isize).cast::<()>())
255 $($tt)*
256 )
257 };
258 (($v:expr) + ($e:expr) $($tt:tt)*) => {
259 $crate::_get_addr0!(
260 ($v.cast::<u8>().offset($e as isize).cast::<()>())
261 $($tt)*
262 )
263 };
264 (($v:expr) - $e:literal $($tt:tt)*) => {
265 $crate::_get_addr0!(
266 ($v.cast::<u8>().offset(-($e as isize)).cast::<()>())
267 $($tt)*
268 )
269 };
270 (($v:expr) - ($e:expr) $($tt:tt)*) => {
271 $crate::_get_addr0!(
272 ($v.cast::<u8>().offset(-($e as isize)).cast::<()>())
273 $($tt)*
274 )
275 }
276}
277
278#[macro_export]
279macro_rules! symbol_fn {
280 () => {};
281 (
282 ($($tt:tt)*) $vis:vis $(extern $cc:literal)? fn $name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
283 $($tta:tt)*
284 ) => {
285 $crate::getfn! {
286 (#[allow(unused_unsafe)] unsafe { ::core::mem::transmute($crate::get_addr!($($tt)*)) }) $vis $(extern $cc)? fn $name($($arg : $argtype),*) $(-> $ret)?;
287 }
288
289 $crate::symbol_fn!($($tta)*);
290 };
291 (
292 ($($tt:tt)*) $vis:vis unsafe $(extern $cc:literal)? fn $name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
293 $($tta:tt)*
294 ) => {
295 $crate::getfn! {
296 (#[allow(unused_unsafe)] unsafe { ::core::mem::transmute($crate::get_addr!($($tt)*)) }) $vis unsafe $(extern $cc)? fn $name($($arg : $argtype),*) $(-> $ret)?;
297 }
298
299 $crate::symbol_fn!($($tta)*);
300 };
301 (
302 ($($tt:tt)*) $vis:vis $(extern $cc:literal)? fn Self::$name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
303 $($tta:tt)*
304 ) => {
305 $crate::getfn! {
306 (#[allow(unused_unsafe)] unsafe { ::core::mem::transmute($crate::get_addr!($($tt)*)) }) $vis $(extern $cc)? fn Self::$name($($arg : $argtype),*) $(-> $ret)?;
307 }
308
309 $crate::symbol_fn!($($tta)*);
310 };
311 (
312 ($($tt:tt)*) $vis:vis unsafe $(extern $cc:literal)? fn Self::$name:ident($($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
313 $($tta:tt)*
314 ) => {
315 $crate::getfn! {
316 (#[allow(unused_unsafe)] unsafe { ::core::mem::transmute($crate::get_addr!($($tt)*)) }) $vis unsafe $(extern $cc)? fn Self::$name($($arg : $argtype),*) $(-> $ret)?;
317 }
318
319 $crate::symbol_fn!($($tta)*);
320 };
321 (
322 ($($tt:tt)*) $vis:vis $(extern $cc:literal)? fn Self::$name:ident([$($self:tt)+] $($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
323 $($tta:tt)*
324 ) => {
325 $crate::getfn! {
326 (#[allow(unused_unsafe)] unsafe { ::core::mem::transmute($crate::get_addr!($($tt)*)) }) $vis $(extern $cc)? fn Self::$name([$($self)+] $($arg : $argtype),*) $(-> $ret)?;
327 }
328
329 $crate::symbol_fn!($($tta)*);
330 };
331 (
332 ($($tt:tt)*) $vis:vis unsafe $(extern $cc:literal)? fn Self::$name:ident([$($self:tt)+] $($arg:ident : $argtype:ty),* $(,)?) $(-> $ret:ty)?;
333 $($tta:tt)*
334 ) => {
335 $crate::getfn! {
336 (#[allow(unused_unsafe)] unsafe { ::core::mem::transmute($crate::get_addr!($($tt)*)) }) $vis unsafe $(extern $cc)? fn Self::$name([$($self)+] $($arg : $argtype),*) $(-> $ret)?;
337 }
338
339 $crate::symbol_fn!($($tta)*);
340 };
341}
342
343#[macro_export]
344macro_rules! symbol_static {
345 () => {};
346 (($($tt:tt)*) $vis:vis static $name:ident: $ty:ty; $($tta:tt)*) => {
347 $vis const $name: $crate::SymbolStatic<$ty> = unsafe { $crate::SymbolStatic::_new(|| {
348 $crate::get_addr!($($tt)*)
349 }) };
350 $crate::symbol_static!($($tta)*);
351 };
352 (($($tt:tt)*) $vis:vis static mut $name:ident: $ty:ty; $($tta:tt)*) => {
353 ::core::compile_error!("static muts are unsupported. consider using atomics or `static X: UnsafeCell<T>`.");
354 }
355}
356
357
358use core::marker::PhantomData;
361use core::ops::Deref;
362
363#[derive(Copy, Clone)]
364pub struct SymbolStatic<T: Sync>(PhantomData<T>, fn() -> *mut ());
365
366impl<T: Sync> Deref for SymbolStatic<T> {
367 type Target = T;
368 fn deref(&self) -> &T { unsafe { &*(self.1() as *const T) } }
369}
370
371impl<T: Sync> SymbolStatic<T> {
372 #[doc(hidden)]
373 pub const unsafe fn _new(x: fn() -> *mut ()) -> Self {
374 Self(PhantomData, x)
375 }
376}