1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use crate::*;

macro_rules! def_api {
    (
struct GodotApi {
    core {
        $(
            $clabel:ident($cst:ident, $cver_maj:expr, $cver_min: expr) {
                $(
                    pub $core_name:ident : $core_ty:ty,
                )*
            }
        )*
    }
    extensions {
        $(
            $elabel:ident($ety_key:ident, $est:ident, $ever_maj:expr, $ever_min: expr) {
                $(
                    pub $ext_name:ident : $ext_ty:ty,
                )*
            }
        )*
    }
}
    ) => (
#[derive(Clone)]
pub struct GodotApi {
    $(
    $(
        pub $core_name: $core_ty,
    )*
    )*

    $(
    $(
        pub $ext_name: $ext_ty,
    )*
    )*
}

impl GodotApi {
    pub unsafe fn from_raw(api_raw: *const godot_gdnative_core_api_struct) -> GodotApi {
        $(
            let mut $clabel: Option<&$cst> = None;
        )*
        $(
            let mut $elabel: Option<&$est> = None;
        )*

        let api = &*api_raw;
        for i in 0 .. api.num_extensions {
            let ext = api.extensions.offset(i as _);

            let mut ext_api_ptr = *ext as *const godot_gdnative_api_struct;
            while !ext_api_ptr.is_null() {
                $(
                    if (&*ext_api_ptr).type_ == $ety_key as u32 &&
                        ((&*ext_api_ptr).version.major == $ever_maj)
                        && ((&*ext_api_ptr).version.minor == $ever_min) {
                        $elabel = Some(&*(ext_api_ptr as *const $est));
                    }
                )*

                ext_api_ptr = (&*ext_api_ptr).next;
            }
        }

        {
            let mut core_api_ptr = api_raw as *const godot_gdnative_api_struct;
            while !core_api_ptr.is_null() {
                $(
                    if ((&*core_api_ptr).version.major == $cver_maj)
                    && ((&*core_api_ptr).version.minor == $cver_min) {
                        $clabel = Some(&*(core_api_ptr as *const $cst));
                    }
                )*

                core_api_ptr = (&*core_api_ptr).next;
            }
        }

        $(
            let $clabel: &$cst = $clabel.expect(concat!("Missing core API: ", stringify!($clabel)));
        )*
        $(
            let $elabel: &$est = $elabel.expect(concat!("Missing extension: ", stringify!($elabel)));
        )*
        GodotApi {
            $(
                $(
                    $core_name: $clabel.$core_name.expect(concat!("Missing function: ", stringify!($core_name))),
                )*
            )*
            $(
                $(
                    $ext_name: $elabel.$ext_name.expect(concat!("Missing function: ", stringify!($ext_name))),
                )*
            )*
        }
    }
}
    )
}

include!(concat!(env!("OUT_DIR"), "/api_wrapper.rs"));