Skip to content

Commit 422faba

Browse files
committed
finalize static func implementation
1 parent 0ddbed9 commit 422faba

File tree

6 files changed

+269
-205
lines changed

6 files changed

+269
-205
lines changed

godot-core/src/builtin/meta/signature.rs

Lines changed: 69 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@ pub trait SignatureTuple {
1818
fn param_metadata(index: i32) -> sys::GDExtensionClassMethodArgumentMetadata;
1919

2020
unsafe fn varcall<C: GodotClass>(
21-
instance_ptr: sys::GDExtensionClassInstancePtr,
22-
args_ptr: *const sys::GDExtensionConstVariantPtr,
23-
ret: sys::GDExtensionVariantPtr,
24-
err: *mut sys::GDExtensionCallError,
25-
func: fn(&C, Self::Params) -> Self::Ret,
26-
method_name: &str,
27-
);
28-
29-
unsafe fn varcall_mut<C: GodotClass>(
3021
instance_ptr: sys::GDExtensionClassInstancePtr,
3122
args_ptr: *const sys::GDExtensionConstVariantPtr,
3223
ret: sys::GDExtensionVariantPtr,
@@ -38,21 +29,11 @@ pub trait SignatureTuple {
3829
// Note: this method imposes extra bounds on GodotFfi, which may not be implemented for user types.
3930
// We could fall back to varcalls in such cases, and not require GodotFfi categorically.
4031
unsafe fn ptrcall<C: GodotClass>(
41-
instance_ptr: sys::GDExtensionClassInstancePtr,
42-
args_ptr: *const sys::GDExtensionConstTypePtr,
43-
ret: sys::GDExtensionTypePtr,
44-
func: fn(&C, Self::Params) -> Self::Ret,
45-
method_name: &str,
46-
call_type: sys::PtrcallType,
47-
);
48-
49-
// Note: this method imposes extra bounds on GodotFfi, which may not be implemented for user types.
50-
// We could fall back to varcalls in such cases, and not require GodotFfi categorically.
51-
unsafe fn ptrcall_mut<C: GodotClass>(
5232
instance_ptr: sys::GDExtensionClassInstancePtr,
5333
args_ptr: *const sys::GDExtensionConstTypePtr,
5434
ret: sys::GDExtensionTypePtr,
5535
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
36+
method_name: &str,
5637
call_type: sys::PtrcallType,
5738
);
5839
}
@@ -130,122 +111,100 @@ macro_rules! impl_signature_for_tuple {
130111
args_ptr: *const sys::GDExtensionConstVariantPtr,
131112
ret: sys::GDExtensionVariantPtr,
132113
err: *mut sys::GDExtensionCallError,
133-
func: fn(&C, Self::Params) -> Self::Ret,
134-
method_name: &str,
135-
) {
136-
$crate::out!("varcall: {}", method_name);
137-
138-
let storage = unsafe { crate::private::as_storage::<C>(instance_ptr) };
139-
let instance = storage.get();
140-
141-
let args = ( $(
142-
{
143-
let variant = unsafe { &*(*args_ptr.offset($n) as *mut Variant) }; // TODO from_var_sys
144-
let arg = <$Pn as FromVariant>::try_from_variant(variant)
145-
.unwrap_or_else(|e| param_error::<$Pn>(method_name, $n, variant));
146-
147-
arg
148-
},
149-
)* );
150-
151-
let ret_val = func(&*instance, args);
152-
let ret_variant = <$R as ToVariant>::to_variant(&ret_val); // TODO write_sys
153-
unsafe {
154-
*(ret as *mut Variant) = ret_variant;
155-
(*err).error = sys::GDEXTENSION_CALL_OK;
156-
}
157-
}
158-
159-
#[inline]
160-
unsafe fn varcall_mut<C : GodotClass>(
161-
instance_ptr: sys::GDExtensionClassInstancePtr,
162-
args_ptr: *const sys::GDExtensionConstVariantPtr,
163-
ret: sys::GDExtensionVariantPtr,
164-
err: *mut sys::GDExtensionCallError,
165114
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
166115
method_name: &str,
167116
) {
168117
$crate::out!("varcall: {}", method_name);
169118

170-
let args = ( $(
171-
{
172-
let variant = unsafe { &*(*args_ptr.offset($n) as *mut Variant) }; // TODO from_var_sys
173-
let arg = <$Pn as FromVariant>::try_from_variant(variant)
174-
.unwrap_or_else(|e| param_error::<$Pn>(method_name, $n, variant));
175-
176-
arg
177-
},
178-
)* );
119+
let args = ($(
120+
unsafe { varcall_arg::<$Pn, $n>(args_ptr, method_name) },
121+
)*) ;
179122

180-
let ret_val = func(instance_ptr, args);
181-
let ret_variant = <$R as ToVariant>::to_variant(&ret_val); // TODO write_sys
182-
unsafe {
183-
*(ret as *mut Variant) = ret_variant;
184-
(*err).error = sys::GDEXTENSION_CALL_OK;
185-
}
123+
varcall_return::<$R>(func(instance_ptr, args), ret, err)
186124
}
187125

188126
#[inline]
189127
unsafe fn ptrcall<C : GodotClass>(
190128
instance_ptr: sys::GDExtensionClassInstancePtr,
191129
args_ptr: *const sys::GDExtensionConstTypePtr,
192130
ret: sys::GDExtensionTypePtr,
193-
func: fn(&C, Self::Params) -> Self::Ret,
131+
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
194132
method_name: &str,
195133
call_type: sys::PtrcallType,
196134
) {
197135
$crate::out!("ptrcall: {}", method_name);
198136

199-
let storage = unsafe { crate::private::as_storage::<C>(instance_ptr) };
200-
let instance = storage.get();
201-
202-
let args = ( $(
203-
unsafe {
204-
<$Pn as sys::GodotFuncMarshal>::try_from_arg(
205-
sys::force_mut_ptr(*args_ptr.offset($n)),
206-
call_type
207-
)
208-
}
209-
.unwrap_or_else(|e| param_error::<$Pn>(method_name, $n, &e)),
210-
)* );
137+
let args = ($(
138+
unsafe { ptrcall_arg::<$Pn, $n>(args_ptr, method_name, call_type) },
139+
)*) ;
211140

212-
let ret_val = func(&*instance, args);
213141
// SAFETY:
214142
// `ret` is always a pointer to an initialized value of type $R
215143
// TODO: double-check the above
216-
<$R as sys::GodotFuncMarshal>::try_return(ret_val, ret, call_type)
217-
.unwrap_or_else(|ret_val| return_error::<$R>(method_name, &ret_val));
144+
ptrcall_return::<$R>(func(instance_ptr, args), ret, method_name, call_type)
218145
}
146+
}
147+
};
148+
}
219149

220-
#[inline]
221-
unsafe fn ptrcall_mut<C : GodotClass>(
222-
instance_ptr: sys::GDExtensionClassInstancePtr,
223-
args_ptr: *const sys::GDExtensionConstTypePtr,
224-
ret: sys::GDExtensionTypePtr,
225-
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
226-
call_type: sys::PtrcallType,
227-
) {
228-
$crate::out!("ptrcall: {}", method_name);
150+
/// Convert the `N`th argument of `args_ptr` into a value of type `P`.
151+
///
152+
/// # Safety
153+
/// - It must be safe to dereference the pointer at `args_ptr.offset(N)` .
154+
unsafe fn varcall_arg<P: FromVariant, const N: isize>(
155+
args_ptr: *const sys::GDExtensionConstVariantPtr,
156+
method_name: &str,
157+
) -> P {
158+
let variant = &*(*args_ptr.offset(N) as *mut Variant); // TODO from_var_sys
159+
P::try_from_variant(variant)
160+
.unwrap_or_else(|_| param_error::<P>(method_name, N as i32, variant))
161+
}
229162

230-
let args = ( $(
231-
unsafe {
232-
<$Pn as sys::GodotFuncMarshal>::try_from_arg(
233-
sys::force_mut_ptr(*args_ptr.offset($n)),
234-
call_type
235-
)
236-
}
237-
.unwrap_or_else(|e| param_error::<$Pn>(method_name, $n, &e)),
238-
)* );
163+
/// Moves `ret_val` into `ret`.
164+
///
165+
/// # Safety
166+
/// - `ret` must be a pointer to an initialized `Variant`.
167+
/// - It must be safe to write a `Variant` once to `ret`.
168+
/// - It must be safe to write a `sys::GDExtensionCallError` once to `err`.
169+
unsafe fn varcall_return<R: ToVariant>(
170+
ret_val: R,
171+
ret: sys::GDExtensionConstVariantPtr,
172+
err: *mut sys::GDExtensionCallError,
173+
) {
174+
let ret_variant = ret_val.to_variant(); // TODO write_sys
175+
*(ret as *mut Variant) = ret_variant;
176+
(*err).error = sys::GDEXTENSION_CALL_OK;
177+
}
239178

240-
let ret_val = func(instance_ptr, args);
241-
// SAFETY:
242-
// `ret` is always a pointer to an initialized value of type $R
243-
// TODO: double-check the above
244-
<$R as sys::GodotFuncMarshal>::try_return(ret_val, ret, call_type)
245-
.unwrap_or_else(|ret_val| return_error::<$R>(method_name, &ret_val));
246-
}
247-
}
248-
};
179+
/// Convert the `N`th argument of `args_ptr` into a value of type `P`.
180+
///
181+
/// # Safety
182+
/// - It must be safe to dereference the address at `args_ptr.offset(N)` .
183+
/// - The pointer at `args_ptr.offset(N)` must follow the safety requirements as laid out in
184+
/// [`GodotFuncMarshal::try_from_arg`][sys::GodotFuncMarshal::try_from_arg].
185+
unsafe fn ptrcall_arg<P: sys::GodotFuncMarshal, const N: isize>(
186+
args_ptr: *const sys::GDExtensionConstTypePtr,
187+
method_name: &str,
188+
call_type: sys::PtrcallType,
189+
) -> P {
190+
P::try_from_arg(sys::force_mut_ptr(*args_ptr.offset(N)), call_type)
191+
.unwrap_or_else(|e| param_error::<P>(method_name, N as i32, &e))
192+
}
193+
194+
/// Moves `ret_val` into `ret`.
195+
///
196+
/// # Safety
197+
/// `ret_val`, `ret`, and `call_type` must follow the safety requirements as laid out in
198+
/// [`GodotFuncMarshal::try_return`](sys::GodotFuncMarshal::try_return).
199+
unsafe fn ptrcall_return<R: sys::GodotFuncMarshal + std::fmt::Debug>(
200+
ret_val: R,
201+
ret: sys::GDExtensionTypePtr,
202+
method_name: &str,
203+
call_type: sys::PtrcallType,
204+
) {
205+
ret_val
206+
.try_return(ret, call_type)
207+
.unwrap_or_else(|ret_val| return_error::<R>(method_name, &ret_val))
249208
}
250209

251210
fn param_error<P>(method_name: &str, index: i32, arg: &impl Debug) -> ! {

0 commit comments

Comments
 (0)