gdnative 0.3.0

The Godot game engine's gdnative bindings.
Documentation
use super::*;

pub trait GodotType: Sized {
    fn to_variant(&self) -> Variant;
    fn from_variant(variant: &Variant) -> Option<Self>;

    fn from_sys_variant(variant: &sys::godot_variant) -> Option<Self> {
        Self::from_variant(Variant::cast_ref(variant))
    }
}

impl GodotType for () {
    fn to_variant(&self) -> Variant {
        Variant::new()
    }

    fn from_variant(variant: &Variant) -> Option<Self> {
        if variant.get_type() == VariantType::Nil {
            Some(())
        } else {
            None
        }
    }
}

macro_rules! godot_int_impl {
    ($ty:ty) => (
        impl GodotType for $ty {
            fn to_variant(&self) -> Variant {
                unsafe {
                    let mut ret = sys::godot_variant::default();
                    (get_api().godot_variant_new_int)(&mut ret, i64::from(*self));
                    Variant(ret)
                }
            }

            fn from_variant(variant: &Variant) -> Option<Self> {
                unsafe {
                    let api = get_api();
                    if (api.godot_variant_get_type)(&variant.0) == sys::godot_variant_type::GODOT_VARIANT_TYPE_INT {
                        Some((api.godot_variant_as_int)(&variant.0) as Self)
                    } else {
                        None
                    }
                }
            }
        }
    )
}

godot_int_impl!(i8);
godot_int_impl!(i16);
godot_int_impl!(i32);
godot_int_impl!(i64);

macro_rules! godot_uint_impl {
    ($ty:ty) => (
        impl GodotType for $ty {
            fn to_variant(&self) -> Variant {
                unsafe {
                    let mut ret = sys::godot_variant::default();
                    (get_api().godot_variant_new_uint)(&mut ret, u64::from(*self));
                    Variant(ret)
                }
            }

            fn from_variant(variant: &Variant) -> Option<Self> {
                unsafe {
                    let api = get_api();
                    if (api.godot_variant_get_type)(&variant.0) == sys::godot_variant_type::GODOT_VARIANT_TYPE_INT {
                        Some((api.godot_variant_as_uint)(&variant.0) as Self)
                    } else {
                        None
                    }
                }
            }
        }
    )
}

godot_uint_impl!(u8);
godot_uint_impl!(u16);
godot_uint_impl!(u32);
godot_uint_impl!(u64);


impl GodotType for f32 {
    fn to_variant(&self) -> Variant {
        unsafe {
            let mut ret = sys::godot_variant::default();
            (get_api().godot_variant_new_real)(&mut ret, f64::from(*self));
            Variant(ret)
        }
    }

    fn from_variant(variant: &Variant) -> Option<Self> {
        unsafe {
            let api = get_api();
            if (api.godot_variant_get_type)(&variant.0) == sys::godot_variant_type::GODOT_VARIANT_TYPE_REAL {
                Some((api.godot_variant_as_real)(&variant.0) as Self)
            } else {
                None
            }
        }
    }
}

impl GodotType for f64 {
    fn to_variant(&self) -> Variant {
        unsafe {
            let mut ret = sys::godot_variant::default();
            (get_api().godot_variant_new_real)(&mut ret, *self);
            Variant(ret)
        }
    }

    fn from_variant(variant: &Variant) -> Option<Self> {
        unsafe {
            let api = get_api();
            if (api.godot_variant_get_type)(&variant.0) == sys::godot_variant_type::GODOT_VARIANT_TYPE_REAL {
                Some((api.godot_variant_as_real)(&variant.0) as Self)
            } else {
                None
            }
        }
    }
}

impl GodotType for String {
    fn to_variant(&self) -> Variant {
        Variant::from_str(&self)
    }

    fn from_variant(variant: &Variant) -> Option<Self> {
        unsafe {
            let api = get_api();
            if (api.godot_variant_get_type)(&variant.0) == sys::godot_variant_type::GODOT_VARIANT_TYPE_STRING {
                let mut gd_variant = (api.godot_variant_as_string)(&variant.0);
                let tmp = (api.godot_string_utf8)(&gd_variant);
                let ret = ::std::ffi::CStr::from_ptr((api.godot_char_string_get_data)(&tmp) as *const _)
                    .to_string_lossy()
                    .into_owned();
                (api.godot_string_destroy)(&mut gd_variant);
                Some(ret)
            } else {
                None
            }
        }
    }
}