fn_ptr/base.rs
1use core::{
2 fmt::{Debug, Pointer},
3 hash::Hash,
4 panic::{RefUnwindSafe, UnwindSafe},
5};
6
7use crate::{
8 AsSafe, AsUnsafe, WithAbi, WithSafety,
9 abi::Abi,
10 make_safe, make_unsafe,
11 marker::{self, Safe, Unsafe},
12 with_abi, with_safety,
13};
14
15ffi_opaque::opaque! {
16 /// A struct representing an opaque function.
17 pub struct OpaqueFn;
18}
19
20/// Type alias for a raw untyped function pointer.
21pub type UntypedFnPtr = *const OpaqueFn;
22
23cfg_tt::cfg_tt! {
24/// Marker trait for all function pointers.
25pub trait FnPtr:
26 PartialEq
27 + Eq
28 + PartialOrd
29 + Ord
30 + Hash
31 + Pointer
32 + Debug
33 + Clone
34 + Copy
35 + Send
36 + Sync
37 + Unpin
38 + UnwindSafe
39 + RefUnwindSafe
40 + Sized
41 #[cfg(nightly_build)]
42 (+ core::marker::FnPtr)
43{
44 /// The argument types as a tuple.
45 type Args;
46
47 /// The return type.
48 type Output;
49
50 /// Marker type denoting arity
51 type ArityMarker: marker::Arity;
52 /// Marker type denoting safety
53 type SafetyMarker: marker::Safety;
54 /// Marker type denoting abi
55 type AbiMarker: marker::Abi;
56
57 /// The function's arity (number of arguments).
58 const ARITY: usize;
59
60 /// Whether the function pointer is safe (fn) or unsafe (unsafe fn).
61 const IS_SAFE: bool;
62
63 /// Whether the function pointer uses an extern calling convention.
64 const IS_EXTERN: bool;
65
66 /// The ABI associated with this function pointer.
67 const ABI: Abi;
68
69 /// Returns the address of this function.
70 #[must_use]
71 fn addr(&self) -> usize {
72 self.as_ptr() as usize
73 }
74 /// Constructs an instance from an address.
75 ///
76 /// # Safety
77 /// The given pointer has to point to a function of the correct type.
78 #[must_use]
79 unsafe fn from_addr(addr: usize) -> Self {
80 unsafe { Self::from_ptr(addr as UntypedFnPtr) }
81 }
82 /// Returns a untyped function pointer for this function.
83 #[must_use]
84 fn as_ptr(&self) -> UntypedFnPtr;
85 /// Constructs an instance from an untyped function pointer.
86 ///
87 /// # Safety
88 /// The given pointer has to point to a function of the correct type.
89 #[must_use]
90 #[allow(clippy::missing_safety_doc)] // false positive?
91 unsafe fn from_ptr(ptr: UntypedFnPtr) -> Self;
92
93 /// Produces an unsafe version of this function pointer.
94 #[must_use]
95 fn as_unsafe(&self) -> make_unsafe!(Self) where Self: AsUnsafe {
96 unsafe { FnPtr::from_ptr(self.as_ptr()) }
97 }
98
99 /// Produces a safe version of this function pointer.
100 ///
101 /// # Safety
102 /// Caller must ensure the underlying function is actually safe to call.
103 #[must_use]
104 unsafe fn as_safe(&self) -> make_safe!(Self) where Self: AsSafe {
105 unsafe { FnPtr::from_ptr(self.as_ptr()) }
106 }
107
108 /// Produces a version of this function pointer with the given ABI.
109 ///
110 /// # Safety
111 /// Caller must ensure that the resulting ABI transformation is sound.
112 #[must_use]
113 unsafe fn with_abi<Abi: marker::Abi>(&self) -> with_abi!(Abi, Self)
114 where
115 Self: WithAbi<Abi>,
116 {
117 unsafe { FnPtr::from_ptr(self.as_ptr()) }
118 }
119
120 /// Produces a version of this function pointer with the given safety.
121 ///
122 /// # Safety
123 /// Caller must ensure that this function pointer is safe when casting to a safe function.
124 #[must_use]
125 unsafe fn with_safety<Safety: marker::Safety>(&self) -> with_safety!(Safety, Self)
126 where
127 Self: WithSafety<Safety>,
128 {
129 unsafe { FnPtr::from_ptr(self.as_ptr()) }
130 }
131}
132}
133
134/// Marker trait for all callable *safe* function pointer types (`fn` / `extern fn`).
135pub trait SafeFnPtr: FnPtr<SafetyMarker = Safe> {
136 /// Invokes the function pointed to with the given args.
137 ///
138 /// # Examples
139 ///
140 /// ```
141 /// # use fn_ptr::SafeFnPtr;
142 /// fn add(a: i32, b: i32) -> i32 { a + b }
143 ///
144 /// let f: fn(i32, i32) -> i32 = add;
145 /// let result = f.invoke((2, 3));
146 /// assert_eq!(result, 5);
147 /// ```
148 // NOTE: Can't use "call" due to fn_traits feature
149 fn invoke(&self, args: Self::Args) -> Self::Output;
150}
151
152/// Marker trait for all callable *unsafe* function pointer types (`unsafe fn` / `unsafe extern fn`).
153pub trait UnsafeFnPtr: FnPtr<SafetyMarker = Unsafe> {
154 /// Invokes the function pointed to with the given args.
155 ///
156 /// # Safety
157 /// Calling this function pointer is unsafe because the function may have
158 /// invariants that must be manually upheld by the caller.
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// # use fn_ptr::UnsafeFnPtr;
164 /// unsafe fn add(a: *const i32, b: *const i32) -> i32 { *a + *b }
165 ///
166 /// let f: unsafe fn(*const i32, *const i32) -> i32 = add;
167 /// let result = unsafe { f.invoke((&2, &3)) };
168 /// assert_eq!(result, 5);
169 /// ```
170 // NOTE: Can't use "call" due to fn_traits feature
171 unsafe fn invoke(&self, args: Self::Args) -> Self::Output;
172}
173
174/// Marker trait for all *static* function pointer types.
175/// The return type and all parameter types have to be `'static`.
176pub trait StaticFnPtr: FnPtr + 'static {}
177
178/// Marker trait implemented for function pointers of a specific ABI.
179///
180/// For example:
181/// - `HasAbi<marker::C>` for `extern "C" fn(...)`
182/// - `HasAbi<marker::Sysv64>` for `extern "sysv64" fn(...)`
183pub trait HasAbi<Abi: marker::Abi>: FnPtr {}
184
185/// Marker trait denoting the safety of a function pointer type.
186///
187/// For example:
188/// - `HasSafety<Safe>` for `extern "C" fn(...)`
189/// - `HasSafety<Unsafe>` for `unsafe fn(...)`
190pub trait HasSafety<Safety: marker::Safety> {}
191impl<F: FnPtr> HasSafety<F::SafetyMarker> for F {}