Skip to content

Commit 5719363

Browse files
committed
- Document stuff
- Seal `GodotType`
1 parent d4cc89a commit 5719363

File tree

8 files changed

+125
-9
lines changed

8 files changed

+125
-9
lines changed

godot-core/src/builtin/meta/godot_compat/impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ where
3434
{
3535
fn try_from_godot(via: Self::Via) -> Option<Self> {
3636
match via {
37-
Some(via) => return T::try_from_godot(via).map(Some),
37+
Some(via) => T::try_from_godot(via).map(Some),
3838
None => Some(None),
3939
}
4040
}

godot-core/src/builtin/meta/godot_compat/mod.rs

+33
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,69 @@ use crate::builtin::{Variant, VariantConversionError};
1212

1313
use super::{GodotFfiVariant, GodotType};
1414

15+
/// Indicates that a type has some canonical Godot type that can represent it.
16+
///
17+
/// The type specified here is what will be used to pass this type across to ffi-boundary to/from Godot.
18+
/// Generally [`ToGodot`] needs to be implemented to pass a type to Godot, and [`FromGodot`] to receive this
19+
/// type from Godot.
1520
pub trait GodotCompatible {
21+
/// The type used for ffi-passing.
1622
type Via: GodotType;
1723
}
1824

25+
/// Defines the canonical conversion to Godot for a type.
26+
///
27+
/// It is assumed that all the methods return equal values given equal inputs. Additionally it is assumed
28+
/// that if [`FromGodot`] is implemented, converting to Godot and back again will return a value equal to the
29+
/// starting value.
30+
///
31+
/// Violating these assumptions is safe but will give unexpected results.
1932
pub trait ToGodot: Sized + GodotCompatible {
33+
/// Converts this type to the Godot type by reference, usually by cloning.
2034
fn to_godot(&self) -> Self::Via;
2135

36+
/// Converts this type to the Godot type.
2237
fn into_godot(self) -> Self::Via {
2338
self.to_godot()
2439
}
2540

41+
/// Converts this type to a [Variant].
2642
fn to_variant(&self) -> Variant {
2743
self.to_godot().to_ffi().ffi_to_variant()
2844
}
2945
}
3046

47+
/// Defines the canonical conversion from Godot for a type.
48+
///
49+
/// It is assumed that all the methods return equal values given equal inputs. Additionally it is assumed
50+
/// that if [`ToGodot`] is implemented, converting to Godot and back again will return a value equal to the
51+
/// starting value.
52+
///
53+
/// Violating these assumptions is safe but will give unexpected results.
3154
pub trait FromGodot: Sized + GodotCompatible {
3255
// TODO: better error
56+
/// Performs the conversion.
3357
fn try_from_godot(via: Self::Via) -> Option<Self>;
3458

59+
/// ⚠️ Performs the conversion.
60+
///
61+
/// # Panics
62+
/// If the conversion fails.
3563
fn from_godot(via: Self::Via) -> Self {
3664
Self::try_from_godot(via).unwrap()
3765
}
3866

67+
/// Performs the conversion from a [`Variant`].
3968
fn try_from_variant(variant: &Variant) -> Result<Self, VariantConversionError> {
4069
let ffi = <Self::Via as GodotType>::Ffi::ffi_from_variant(variant)?;
4170
let via = Self::Via::try_from_ffi(ffi).ok_or(VariantConversionError::BadValue)?;
4271
Self::try_from_godot(via).ok_or(VariantConversionError::BadValue)
4372
}
4473

74+
/// ⚠️ Performs the conversion from a [`Variant`].
75+
///
76+
/// # Panics
77+
/// If the conversion fails.
4578
fn from_variant(variant: &Variant) -> Self {
4679
Self::try_from_variant(variant).unwrap()
4780
}

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

+78-1
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,89 @@ use crate::builtin::*;
2525
use crate::engine::global;
2626
use registration::method::MethodParamOrReturnInfo;
2727

28+
/// Conversion of GodotFfi-types into/from [`Variant`].
2829
pub trait GodotFfiVariant: Sized + GodotFfi {
2930
fn ffi_to_variant(&self) -> Variant;
3031
fn ffi_from_variant(variant: &Variant) -> Result<Self, VariantConversionError>;
3132
}
3233

33-
pub trait GodotType: GodotCompatible<Via = Self> + ToGodot + FromGodot {
34+
mod sealed {
35+
// To ensure the user does not implement `GodotType` for their own types.
36+
37+
use godot_ffi::GodotNullableFfi;
38+
39+
use super::GodotType;
40+
use crate::builtin::*;
41+
use crate::obj::*;
42+
43+
pub trait Sealed {}
44+
45+
impl Sealed for Aabb {}
46+
impl Sealed for Basis {}
47+
impl Sealed for Callable {}
48+
impl Sealed for Vector2 {}
49+
impl Sealed for Vector3 {}
50+
impl Sealed for Vector4 {}
51+
impl Sealed for Vector2i {}
52+
impl Sealed for Vector3i {}
53+
impl Sealed for Vector4i {}
54+
impl Sealed for Quaternion {}
55+
impl Sealed for Color {}
56+
impl Sealed for GodotString {}
57+
impl Sealed for StringName {}
58+
impl Sealed for NodePath {}
59+
impl Sealed for PackedByteArray {}
60+
impl Sealed for PackedInt32Array {}
61+
impl Sealed for PackedInt64Array {}
62+
impl Sealed for PackedFloat32Array {}
63+
impl Sealed for PackedFloat64Array {}
64+
impl Sealed for PackedStringArray {}
65+
impl Sealed for PackedVector2Array {}
66+
impl Sealed for PackedVector3Array {}
67+
impl Sealed for PackedColorArray {}
68+
impl Sealed for Plane {}
69+
impl Sealed for Projection {}
70+
impl Sealed for Rid {}
71+
impl Sealed for Rect2 {}
72+
impl Sealed for Rect2i {}
73+
impl Sealed for Signal {}
74+
impl Sealed for Transform2D {}
75+
impl Sealed for Transform3D {}
76+
impl Sealed for Dictionary {}
77+
impl Sealed for bool {}
78+
impl Sealed for i64 {}
79+
impl Sealed for i32 {}
80+
impl Sealed for i16 {}
81+
impl Sealed for i8 {}
82+
impl Sealed for u64 {}
83+
impl Sealed for u32 {}
84+
impl Sealed for u16 {}
85+
impl Sealed for u8 {}
86+
impl Sealed for f64 {}
87+
impl Sealed for f32 {}
88+
impl Sealed for () {}
89+
impl Sealed for Variant {}
90+
impl<T: GodotType> Sealed for Array<T> {}
91+
impl<T: GodotClass> Sealed for RawGd<T> {}
92+
impl<T: GodotClass> Sealed for Gd<T> {}
93+
impl<T> Sealed for Option<T>
94+
where
95+
T: GodotType,
96+
T::Ffi: GodotNullableFfi,
97+
{
98+
}
99+
}
100+
101+
/// Types that can represent some Godot type.
102+
///
103+
/// This trait cannot be implemented for custom user types, for that you should see [`GodotCompatible`]
104+
/// instead.
105+
///
106+
/// Unlike [`GodotFfi`], types implementing this trait don't need to fully represent its corresponding Godot
107+
/// type. For instance [`i32`] does not implement [`GodotFfi`] because it cannot represent all values of
108+
/// Godot's `int` type, however it does implement `GodotType` because we can set the metadata of values with
109+
/// this type to indicate that they are 32 bits large.
110+
pub trait GodotType: GodotCompatible<Via = Self> + ToGodot + FromGodot + sealed::Sealed {
34111
type Ffi: GodotFfiVariant;
35112

36113
fn to_ffi(&self) -> Self::Ffi;

godot-core/src/obj/raw.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ where
449449
}
450450
}
451451

452-
unsafe impl<T: GodotClass> GodotNullableFfi for RawGd<T> {
452+
impl<T: GodotClass> GodotNullableFfi for RawGd<T> {
453453
fn flatten_option(opt: Option<Self>) -> Self {
454454
match opt {
455455
Some(raw) => raw,

godot-ffi/src/godot_ffi.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use crate as sys;
88
use std::marker::PhantomData;
99

10+
/// Types that can directly and fully represent some Godot type.
11+
///
1012
/// Adds methods to convert from and to Godot FFI pointers.
1113
/// See [crate::ffi_methods] for ergonomic implementation.
1214
///
@@ -132,7 +134,10 @@ pub unsafe fn from_sys_init_or_init_default<T: GodotFfi>(
132134

133135
// ----------------------------------------------------------------------------------------------------------------------------------------------
134136

135-
pub unsafe trait GodotNullableFfi: Sized + GodotFfi {
137+
/// Types that can represent null-values.
138+
///
139+
/// Used to blanket implement various conversions over `Option<T>`.
140+
pub trait GodotNullableFfi: Sized + GodotFfi {
136141
fn flatten_option(opt: Option<Self>) -> Self;
137142
fn is_null(&self) -> bool;
138143
}

godot-macros/src/class/data_models/property.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
173173

174174
export_tokens.push(quote! {
175175
use ::godot::sys::GodotFfi;
176-
176+
177177
let (hint, hint_string) = #hint;
178178
let usage = #usage_flags;
179179

godot-macros/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -423,13 +423,13 @@ pub fn derive_godot_compatible(input: TokenStream) -> TokenStream {
423423
translate(input, derive::derive_godot_compatible)
424424
}
425425

426-
/// Derive macro for [ToVariant](../builtin/trait.ToVariant.html) on structs or enums.
426+
/// Derive macro for [ToGodot](../builtin/meta/trait.ToGodot.html) on structs or enums.
427427
///
428428
/// # Example
429429
///
430430
/// ```no_run
431431
/// # use godot::prelude::*;
432-
/// #[derive(FromVariant, ToVariant, PartialEq, Debug)]
432+
/// #[derive(FromGodot, ToGodot, GodotCompatible, PartialEq, Debug)]
433433
/// struct StructNamed {
434434
/// field1: String,
435435
/// field2: i32,
@@ -456,13 +456,13 @@ pub fn derive_to_godot(input: TokenStream) -> TokenStream {
456456
translate(input, derive::derive_to_godot)
457457
}
458458

459-
/// Derive macro for [FromVariant](../builtin/trait.FromVariant.html) on structs or enums.
459+
/// Derive macro for [FromGodot](../builtin/meta/trait.FromVariant.html) on structs or enums.
460460
///
461461
/// # Example
462462
///
463463
/// ```no_run
464464
/// # use godot::prelude::*;
465-
/// #[derive(FromVariant, ToVariant, PartialEq, Debug)]
465+
/// #[derive(FromGodot, ToGodot, GodotCompatible, PartialEq, Debug)]
466466
/// struct StructNamed {
467467
/// field1: String,
468468
/// field2: i32,

itest/rust/build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ macro_rules! push_newtype {
6060
}
6161

6262
impl godot::builtin::meta::ToGodot for $name {
63+
#[allow(clippy::clone_on_copy)]
6364
fn to_godot(&self) -> Self::Via {
6465
self.0.clone()
6566
}

0 commit comments

Comments
 (0)