Skip to content

Commit

Permalink
Merge pull request #467 from lilizoey/feature/godot-convert-result2
Browse files Browse the repository at this point in the history
Make `FromGodot` conversions fallible
  • Loading branch information
Bromeon authored Nov 25, 2023
2 parents 13ab375 + 20b0f50 commit 9016ae2
Show file tree
Hide file tree
Showing 25 changed files with 848 additions and 284 deletions.
11 changes: 7 additions & 4 deletions godot-codegen/src/class_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,8 +925,8 @@ fn make_native_structure(
}

impl FromGodot for *mut #class_name {
fn try_from_godot(via: Self::Via) -> Option<Self> {
Some(via as Self)
fn try_from_godot(via: Self::Via) -> Result<Self, crate::builtin::meta::ConvertError> {
Ok(via as Self)
}
}

Expand All @@ -941,8 +941,8 @@ fn make_native_structure(
}

impl FromGodot for *const #class_name {
fn try_from_godot(via: Self::Via) -> Option<Self> {
Some(via as Self)
fn try_from_godot(via: Self::Via) -> Result<Self, crate::builtin::meta::ConvertError> {
Ok(via as Self)
}
}
};
Expand Down Expand Up @@ -1286,6 +1286,7 @@ fn make_builtin_method_definition(

<CallSig as PtrcallSignatureTuple>::out_builtin_ptrcall::<RetMarshal>(
method_bind,
#method_name_str,
#object_ptr,
args
)
Expand Down Expand Up @@ -1345,6 +1346,7 @@ pub(crate) fn make_utility_function_definition(

<CallSig as PtrcallSignatureTuple>::out_utility_ptrcall(
utility_fn,
#function_name_str,
args
)
};
Expand All @@ -1354,6 +1356,7 @@ pub(crate) fn make_utility_function_definition(

<CallSig as VarcallSignatureTuple>::out_utility_ptrcall_varargs(
utility_fn,
#function_name_str,
args,
varargs
)
Expand Down
3 changes: 2 additions & 1 deletion godot-codegen/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,9 @@ pub fn make_enum_definition(enum_: &Enum) -> TokenStream {
}

impl crate::builtin::meta::FromGodot for #enum_name {
fn try_from_godot(via: Self::Via) -> Option<Self> {
fn try_from_godot(via: Self::Via) -> std::result::Result<Self, crate::builtin::meta::ConvertError> {
<Self as crate::obj::EngineEnum>::try_from_ord(via)
.ok_or_else(|| crate::builtin::meta::FromGodotError::InvalidEnum.into_error(via))
}
}

Expand Down
51 changes: 39 additions & 12 deletions godot-core/src/builtin/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use std::fmt;
use std::marker::PhantomData;
use sys::{ffi_methods, interface_fn, GodotFfi};

use super::meta::{FromGodot, GodotConvert, GodotFfiVariant, GodotType, ToGodot};
use super::meta::{
ConvertError, FromGodot, FromGodotError, FromVariantError, GodotConvert, GodotFfiVariant,
GodotType, ToGodot,
};

/// Godot's `Array` type.
///
Expand Down Expand Up @@ -337,11 +340,18 @@ impl<T: GodotType> Array<T> {
}

/// Checks that the inner array has the correct type set on it for storing elements of type `T`.
fn with_checked_type(self) -> Result<Self, VariantConversionError> {
if self.type_info() == TypeInfo::of::<T>() {
fn with_checked_type(self) -> Result<Self, ConvertError> {
let self_ty = self.type_info();
let target_ty = TypeInfo::of::<T>();

if self_ty == target_ty {
Ok(self)
} else {
Err(VariantConversionError::BadType)
Err(FromGodotError::BadArrayType {
expected: target_ty,
got: self_ty,
}
.into_error(self))
}
}

Expand Down Expand Up @@ -633,11 +643,15 @@ impl<T: GodotType> ToGodot for Array<T> {
fn into_godot(self) -> Self::Via {
self
}

fn to_variant(&self) -> Variant {
self.ffi_to_variant()
}
}

impl<T: GodotType> FromGodot for Array<T> {
fn try_from_godot(via: Self::Via) -> Option<Self> {
Some(via)
fn try_from_godot(via: Self::Via) -> Result<Self, ConvertError> {
Ok(via)
}
}

Expand Down Expand Up @@ -755,15 +769,16 @@ impl<T: GodotType> GodotType for Array<T> {
type Ffi = Self;

fn to_ffi(&self) -> Self::Ffi {
// `to_ffi` is sometimes intentionally called with an array in an invalid state.
self.clone()
}

fn into_ffi(self) -> Self::Ffi {
self
}

fn try_from_ffi(ffi: Self::Ffi) -> Option<Self> {
Some(ffi)
fn try_from_ffi(ffi: Self::Ffi) -> Result<Self, ConvertError> {
Ok(ffi)
}

fn godot_type_name() -> String {
Expand All @@ -781,9 +796,13 @@ impl<T: GodotType> GodotFfiVariant for Array<T> {
}
}

fn ffi_from_variant(variant: &Variant) -> Result<Self, VariantConversionError> {
fn ffi_from_variant(variant: &Variant) -> Result<Self, ConvertError> {
if variant.get_type() != Self::variant_type() {
return Err(VariantConversionError::BadType);
return Err(FromVariantError::BadType {
expected: Self::variant_type(),
got: variant.get_type(),
}
.into_error(variant.clone()));
}

let array = unsafe {
Expand Down Expand Up @@ -992,7 +1011,7 @@ macro_rules! varray {
///
/// We ignore the `script` parameter because it has no impact on typing in Godot.
#[derive(PartialEq, Eq)]
struct TypeInfo {
pub(crate) struct TypeInfo {
variant_type: VariantType,

/// Not a `ClassName` because some values come from Godot engine API.
Expand All @@ -1007,9 +1026,17 @@ impl TypeInfo {
}
}

fn is_typed(&self) -> bool {
pub fn is_typed(&self) -> bool {
self.variant_type != VariantType::Nil
}

pub fn variant_type(&self) -> VariantType {
self.variant_type
}

pub fn class_name(&self) -> &StringName {
&self.class_name
}
}

impl fmt::Debug for TypeInfo {
Expand Down
Loading

0 comments on commit 9016ae2

Please sign in to comment.