godot_core/meta/
method_info.rs

1/*
2 * Copyright (c) godot-rust; Bromeon and contributors.
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 */
7
8use godot_ffi::conv::u32_to_usize;
9
10use crate::builtin::{StringName, Variant};
11use crate::global::MethodFlags;
12use crate::meta::{ClassId, PropertyInfo};
13use crate::sys;
14
15/// Describes a method in Godot.
16///
17/// Abstraction of the low-level `sys::GDExtensionMethodInfo`.
18// Currently used for ScriptInstance.
19// TODO check overlap with (private) ClassMethodInfo.
20#[derive(Clone, Debug)]
21pub struct MethodInfo {
22    pub id: i32,
23    pub method_name: StringName,
24    pub class_name: ClassId,
25    pub return_type: PropertyInfo,
26    pub arguments: Vec<PropertyInfo>,
27    pub default_arguments: Vec<Variant>,
28    pub flags: MethodFlags,
29}
30
31impl MethodInfo {
32    /// Consumes self and turns it into a `sys::GDExtensionMethodInfo`, should be used together with
33    /// [`free_owned_method_sys`](Self::free_owned_method_sys).
34    ///
35    /// This will leak memory unless used together with `free_owned_method_sys`.
36    pub fn into_owned_method_sys(self) -> sys::GDExtensionMethodInfo {
37        use crate::obj::EngineBitfield as _;
38
39        // Destructure self to ensure all fields are used.
40        let Self {
41            id,
42            method_name,
43            // TODO: Do we need this?
44            class_name: _class_name,
45            return_type,
46            arguments,
47            default_arguments,
48            flags,
49        } = self;
50
51        let argument_count: u32 = arguments
52            .len()
53            .try_into()
54            .expect("cannot have more than `u32::MAX` arguments");
55        let arguments = arguments
56            .into_iter()
57            .map(|arg| arg.into_owned_property_sys())
58            .collect::<Box<[_]>>();
59        let arguments = Box::leak(arguments).as_mut_ptr();
60
61        let default_argument_count: u32 = default_arguments
62            .len()
63            .try_into()
64            .expect("cannot have more than `u32::MAX` default arguments");
65        let default_argument = default_arguments
66            .into_iter()
67            .map(|arg| arg.into_owned_var_sys())
68            .collect::<Box<[_]>>();
69        let default_arguments = Box::leak(default_argument).as_mut_ptr();
70
71        sys::GDExtensionMethodInfo {
72            id,
73            name: method_name.into_owned_string_sys(),
74            return_value: return_type.into_owned_property_sys(),
75            argument_count,
76            arguments,
77            default_argument_count,
78            default_arguments,
79            flags: flags.ord().try_into().expect("flags should be valid"),
80        }
81    }
82
83    /// Properly frees a `sys::GDExtensionMethodInfo` created by [`into_owned_method_sys`](Self::into_owned_method_sys).
84    ///
85    /// # Safety
86    ///
87    /// * Must only be used on a struct returned from a call to `into_owned_method_sys`, without modification.
88    /// * Must not be called more than once on a `sys::GDExtensionMethodInfo` struct.
89    #[deny(unsafe_op_in_unsafe_fn)]
90    pub unsafe fn free_owned_method_sys(info: sys::GDExtensionMethodInfo) {
91        // Destructure info to ensure all fields are used.
92        let sys::GDExtensionMethodInfo {
93            name,
94            return_value,
95            flags: _flags,
96            id: _id,
97            argument_count,
98            arguments,
99            default_argument_count,
100            default_arguments,
101        } = info;
102
103        // SAFETY: `name` is a pointer that was returned from `StringName::into_owned_string_sys`, and has not been freed before this.
104        let _name = unsafe { StringName::from_owned_string_sys(name) };
105
106        // SAFETY: `return_value` is a pointer that was returned from `PropertyInfo::into_owned_property_sys`, and has not been freed before
107        // this.
108        unsafe { PropertyInfo::free_owned_property_sys(return_value) };
109
110        // SAFETY:
111        // - `from_raw_parts_mut`: `arguments` comes from `as_mut_ptr()` on a mutable slice of length `argument_count`, and no other
112        //    accesses to the pointer happens for the lifetime of the slice.
113        // - `Box::from_raw`: The slice was returned from a call to `Box::leak`, and we have ownership of the value behind this pointer.
114        let arguments = unsafe {
115            let slice = std::slice::from_raw_parts_mut(arguments, u32_to_usize(argument_count));
116
117            Box::from_raw(slice)
118        };
119
120        for info in arguments.iter() {
121            // SAFETY: These infos were originally created from a call to `PropertyInfo::into_owned_property_sys`, and this method
122            // will not be called again on this pointer.
123            unsafe { PropertyInfo::free_owned_property_sys(*info) }
124        }
125
126        // SAFETY:
127        // - `from_raw_parts_mut`: `default_arguments` comes from `as_mut_ptr()` on a mutable slice of length `default_argument_count`, and no
128        //    other accesses to the pointer happens for the lifetime of the slice.
129        // - `Box::from_raw`: The slice was returned from a call to `Box::leak`, and we have ownership of the value behind this pointer.
130        let default_arguments = unsafe {
131            let slice = std::slice::from_raw_parts_mut(
132                default_arguments,
133                u32_to_usize(default_argument_count),
134            );
135
136            Box::from_raw(slice)
137        };
138
139        for variant in default_arguments.iter() {
140            // SAFETY: These pointers were originally created from a call to `Variant::into_owned_var_sys`, and this method will not be
141            // called again on this pointer.
142            let _variant = unsafe { Variant::from_owned_var_sys(*variant) };
143        }
144    }
145}