Skip to content

Commit 971d8fb

Browse files
committed
Move several verifying traits: object -> object::bounds
1 parent d672c2d commit 971d8fb

File tree

6 files changed

+291
-268
lines changed

6 files changed

+291
-268
lines changed

gdnative-core/src/nativescript/class.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use crate::core_types::{
55
};
66
use crate::nativescript::init::ClassBuilder;
77
use crate::nativescript::{Map, MapMut, MapOwned, UserData};
8+
use crate::object::bounds::{
9+
AssumeSafeLifetime, LifetimeConstraint, RefImplBound, SafeAsRaw, SafeDeref,
10+
};
811
use crate::object::memory::{ManuallyManaged, RefCounted};
912
use crate::object::ownership::{NonUniqueThreadAccess, Shared, ThreadAccess, ThreadLocal, Unique};
10-
use crate::object::{
11-
AssumeSafeLifetime, LifetimeConstraint, QueueFree, RawObject, Ref, RefImplBound, SafeAsRaw,
12-
SafeDeref, TRef,
13-
};
1413
use crate::object::{GodotObject, Instanciable};
14+
use crate::object::{QueueFree, RawObject, Ref, TRef};
1515
use crate::private::{get_api, ReferenceCountedClassPlaceholder};
1616

1717
use super::class_registry;

gdnative-core/src/object/bounds.rs

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
//! Various traits to verify memory policy, ownership policy or lifetime bounds
2+
//! The symbols defined in this module are internal and used to enhance type safety.
3+
//! You typically will not need to work with them.
4+
5+
use crate::object::memory::*;
6+
use crate::object::ownership::*;
7+
use crate::object::*;
8+
9+
// ----------------------------------------------------------------------------------------------------------------------------------------------
10+
// Implementation for RefKind policy
11+
12+
/// Specialization trait depending on [`RefKind`]. This is an internal interface.
13+
pub trait RefKindSpec: Sized {
14+
/// Pointer wrapper that may be `Drop` or not.
15+
#[doc(hidden)]
16+
type PtrWrapper: PtrWrapper;
17+
18+
#[doc(hidden)]
19+
unsafe fn impl_from_maybe_ref_counted<T: GodotObject<RefKind = Self>>(
20+
ptr: NonNull<sys::godot_object>,
21+
) -> Option<Ref<T, Unique>>
22+
where
23+
Self: RefKind;
24+
25+
#[doc(hidden)]
26+
unsafe fn impl_assume_safe<'a, T: GodotObject<RefKind = Self>>(
27+
this: &Ref<T, Shared>,
28+
) -> TRef<'a, T, Shared>
29+
where
30+
Self: RefKind;
31+
32+
#[doc(hidden)]
33+
unsafe fn impl_assume_unique<T: GodotObject<RefKind = Self>>(
34+
this: Ref<T, Shared>,
35+
) -> Ref<T, Unique>
36+
where
37+
Self: RefKind;
38+
39+
#[doc(hidden)]
40+
unsafe fn maybe_add_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>)
41+
where
42+
Self: RefKind;
43+
44+
#[doc(hidden)]
45+
unsafe fn maybe_init_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>)
46+
where
47+
Self: RefKind;
48+
}
49+
50+
impl RefKindSpec for ManuallyManaged {
51+
type PtrWrapper = Forget;
52+
53+
#[inline(always)]
54+
unsafe fn impl_from_maybe_ref_counted<T: GodotObject<RefKind = Self>>(
55+
ptr: NonNull<sys::godot_object>,
56+
) -> Option<Ref<T, Unique>> {
57+
if RawObject::<ReferenceCountedClassPlaceholder>::try_from_sys_ref(ptr).is_some() {
58+
drop(Ref::<ReferenceCountedClassPlaceholder, Unique>::init_from_sys(ptr));
59+
None
60+
} else {
61+
let obj = Ref::<ManuallyManagedClassPlaceholder, Unique>::init_from_sys(ptr);
62+
63+
if obj.as_raw().is_class::<T>() {
64+
Some(obj.cast_unchecked())
65+
} else {
66+
obj.free();
67+
None
68+
}
69+
}
70+
}
71+
72+
#[inline(always)]
73+
unsafe fn impl_assume_safe<'a, T: GodotObject<RefKind = Self>>(
74+
this: &Ref<T, Shared>,
75+
) -> TRef<'a, T, Shared> {
76+
debug_assert!(
77+
this.is_instance_sane(),
78+
"assume_safe called on an invalid pointer"
79+
);
80+
this.assume_safe_unchecked()
81+
}
82+
83+
#[inline(always)]
84+
unsafe fn impl_assume_unique<T: GodotObject<RefKind = Self>>(
85+
this: Ref<T, Shared>,
86+
) -> Ref<T, Unique> {
87+
debug_assert!(
88+
this.is_instance_sane(),
89+
"assume_unique called on an invalid pointer"
90+
);
91+
this.cast_access()
92+
}
93+
94+
#[inline]
95+
unsafe fn maybe_add_ref<T: GodotObject<RefKind = Self>>(_raw: &RawObject<T>) {}
96+
#[inline]
97+
unsafe fn maybe_init_ref<T: GodotObject<RefKind = Self>>(_raw: &RawObject<T>) {}
98+
}
99+
100+
impl RefKindSpec for RefCounted {
101+
type PtrWrapper = UnRef;
102+
103+
#[inline(always)]
104+
unsafe fn impl_from_maybe_ref_counted<T: GodotObject<RefKind = Self>>(
105+
ptr: NonNull<sys::godot_object>,
106+
) -> Option<Ref<T, Unique>> {
107+
if RawObject::<ReferenceCountedClassPlaceholder>::try_from_sys_ref(ptr).is_some() {
108+
let obj = Ref::<ReferenceCountedClassPlaceholder, Unique>::init_from_sys(ptr);
109+
110+
if obj.as_raw().is_class::<T>() {
111+
Some(obj.cast_unchecked())
112+
} else {
113+
None
114+
}
115+
} else {
116+
RawObject::<ManuallyManagedClassPlaceholder>::from_sys_ref_unchecked(ptr).free();
117+
None
118+
}
119+
}
120+
121+
#[inline(always)]
122+
unsafe fn impl_assume_safe<'a, T: GodotObject<RefKind = Self>>(
123+
this: &Ref<T, Shared>,
124+
) -> TRef<'a, T, Shared> {
125+
this.assume_safe_unchecked()
126+
}
127+
128+
#[inline(always)]
129+
unsafe fn impl_assume_unique<T: GodotObject<RefKind = Self>>(
130+
this: Ref<T, Shared>,
131+
) -> Ref<T, Unique> {
132+
this.cast_access()
133+
}
134+
135+
#[inline]
136+
unsafe fn maybe_add_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>) {
137+
raw.add_ref();
138+
}
139+
140+
#[inline]
141+
unsafe fn maybe_init_ref<T: GodotObject<RefKind = Self>>(raw: &RawObject<T>) {
142+
raw.init_ref_count();
143+
}
144+
}
145+
146+
// ----------------------------------------------------------------------------------------------------------------------------------------------
147+
// Drop strategy
148+
149+
/// Specialization trait for `Drop` behavior.
150+
pub trait PtrWrapper {
151+
fn new(ptr: NonNull<sys::godot_object>) -> Self;
152+
fn as_non_null(&self) -> NonNull<sys::godot_object>;
153+
154+
#[inline]
155+
fn as_ptr(&self) -> *mut sys::godot_object {
156+
self.as_non_null().as_ptr()
157+
}
158+
}
159+
160+
/// Simply releases the held object without deallocating it.
161+
#[derive(Copy, Clone)]
162+
pub struct Forget(NonNull<sys::godot_object>);
163+
impl PtrWrapper for Forget {
164+
#[inline]
165+
fn new(ptr: NonNull<sys::godot_object>) -> Self {
166+
Forget(ptr)
167+
}
168+
169+
#[inline]
170+
fn as_non_null(&self) -> NonNull<sys::godot_object> {
171+
self.0
172+
}
173+
}
174+
175+
/// Decrements the reference count on the held object, deallocating it if it's the last ref.
176+
pub struct UnRef(NonNull<sys::godot_object>);
177+
impl PtrWrapper for UnRef {
178+
#[inline]
179+
fn new(ptr: NonNull<sys::godot_object>) -> Self {
180+
UnRef(ptr)
181+
}
182+
183+
#[inline]
184+
fn as_non_null(&self) -> NonNull<sys::godot_object> {
185+
self.0
186+
}
187+
}
188+
impl Drop for UnRef {
189+
#[inline]
190+
fn drop(&mut self) {
191+
unsafe {
192+
let raw = RawObject::<ReferenceCountedClassPlaceholder>::from_sys_ref_unchecked(self.0);
193+
raw.unref_and_free_if_last();
194+
}
195+
}
196+
}
197+
198+
// ----------------------------------------------------------------------------------------------------------------------------------------------
199+
// assume_safe and lifetime bounds
200+
201+
/// Trait for constraining `assume_safe` lifetimes to the one of `&self` when `T` is
202+
/// reference-counted. This is an internal interface.
203+
pub trait LifetimeConstraint<Kind: RefKind> {}
204+
205+
/// Type used to check lifetime constraint depending on `RefKind`. Internal interface.
206+
#[doc(hidden)]
207+
pub struct AssumeSafeLifetime<'a, 'r> {
208+
_marker: PhantomData<(&'a (), &'r ())>,
209+
}
210+
211+
impl<'a, 'r> LifetimeConstraint<ManuallyManaged> for AssumeSafeLifetime<'a, 'r> {}
212+
impl<'a, 'r: 'a> LifetimeConstraint<RefCounted> for AssumeSafeLifetime<'a, 'r> {}
213+
214+
// ----------------------------------------------------------------------------------------------------------------------------------------------
215+
// SafeDeref, SafeAsRaw
216+
217+
/// Trait for combinations of `RefKind` and `ThreadAccess` that can be dereferenced safely.
218+
/// This is an internal interface.
219+
pub unsafe trait SafeDeref<Kind: RefKind, Access: ThreadAccess> {
220+
/// Returns a safe reference to the underlying object.
221+
#[doc(hidden)]
222+
fn impl_as_ref<T: GodotObject<RefKind = Kind>>(this: &Ref<T, Access>) -> TRef<'_, T, Access>;
223+
}
224+
225+
/// Trait for persistent `Ref`s that point to valid objects. This is an internal interface.
226+
pub unsafe trait SafeAsRaw<Kind: RefKind, Access: ThreadAccess> {
227+
/// Returns a raw reference to the underlying object.
228+
#[doc(hidden)]
229+
fn impl_as_raw<T: GodotObject<RefKind = Kind>>(this: &Ref<T, Access>) -> &RawObject<T>;
230+
}
231+
232+
// ----------------------------------------------------------------------------------------------------------------------------------------------
233+
// RefImplBound
234+
235+
/// Struct to be used for various `Ref` trait bounds.
236+
pub struct RefImplBound {
237+
_private: (),
238+
}
239+
240+
unsafe impl SafeDeref<ManuallyManaged, Unique> for RefImplBound {
241+
#[inline]
242+
fn impl_as_ref<T: GodotObject<RefKind = ManuallyManaged>>(
243+
this: &Ref<T, Unique>,
244+
) -> TRef<'_, T, Unique> {
245+
unsafe { this.assume_safe_unchecked() }
246+
}
247+
}
248+
249+
unsafe impl<Access: LocalThreadAccess> SafeDeref<RefCounted, Access> for RefImplBound {
250+
#[inline]
251+
fn impl_as_ref<T: GodotObject<RefKind = RefCounted>>(
252+
this: &Ref<T, Access>,
253+
) -> TRef<'_, T, Access> {
254+
unsafe { this.assume_safe_unchecked() }
255+
}
256+
}
257+
258+
unsafe impl SafeAsRaw<ManuallyManaged, Unique> for RefImplBound {
259+
#[inline]
260+
fn impl_as_raw<T: GodotObject<RefKind = ManuallyManaged>>(
261+
this: &Ref<T, Unique>,
262+
) -> &RawObject<T> {
263+
unsafe { this.as_raw_unchecked() }
264+
}
265+
}
266+
267+
unsafe impl<Access: ThreadAccess> SafeAsRaw<RefCounted, Access> for RefImplBound {
268+
#[inline]
269+
fn impl_as_raw<T: GodotObject<RefKind = RefCounted>>(this: &Ref<T, Access>) -> &RawObject<T> {
270+
unsafe { this.as_raw_unchecked() }
271+
}
272+
}

gdnative-core/src/object/memory.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Marker types to express the memory management method of Godot types.
22
3-
use crate::object::RefKindSpec;
3+
use crate::object::bounds::RefKindSpec;
44

55
/// Marker that indicates that a type is manually managed.
66
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
@@ -10,8 +10,7 @@ pub struct ManuallyManaged;
1010
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
1111
pub struct RefCounted;
1212

13-
/// Trait to parameterize over the memory management markers
14-
/// [`ManuallyManaged`](struct.ManuallyManaged.html) and [`RefCounted`](struct.RefCounted.html).
13+
/// Trait to parameterize over the memory management markers [`ManuallyManaged`] and [`RefCounted`].
1514
///
1615
/// This trait is sealed and has no public members.
1716
pub trait RefKind: RefKindSpec + private::Sealed {}
@@ -21,7 +20,6 @@ impl private::Sealed for ManuallyManaged {}
2120

2221
impl RefKind for RefCounted {}
2322
impl private::Sealed for RefCounted {}
24-
2523
mod private {
2624
pub trait Sealed {}
2725
}

0 commit comments

Comments
 (0)