euroscope-sys 0.0.1

Raw FFI bindings and C++ glue shim for the EuroScope plugin SDK
// Owned-handle selectors and cross-navigation.
//
// EuroScope's Select*/Correlated* methods return handle objects BY VALUE, whose
// internal index we cannot read across the flat C ABI. So each wrapper
// heap-copies the returned handle (`new CX(...)`) and returns the pointer, or
// nullptr when the handle is invalid. The Rust side owns the copy and frees it
// with the matching `es_*_free`. Methods on the copy work because the handle is
// just an index into live EuroScope data.

#include "common.h"

template <typename T>
static void* own(const T& value)
{
    return value.IsValid() ? new T(value) : nullptr;
}

// --- CFlightPlan ---------------------------------------------------------

extern "C" void es_flightplan_free(void* fp) { delete ES_AS(CFlightPlan, fp); }

extern "C" void* es_plugin_flightplan_select_first(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->FlightPlanSelectFirst());
}

extern "C" void* es_plugin_flightplan_select_next(void* plugin, void* current)
{
    return own(ES_AS(CPlugIn, plugin)->FlightPlanSelectNext(*ES_AS(CFlightPlan, current)));
}

extern "C" void* es_plugin_flightplan_select_asel(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->FlightPlanSelectASEL());
}

extern "C" void* es_plugin_flightplan_select(void* plugin, const char* callsign)
{
    return own(ES_AS(CPlugIn, plugin)->FlightPlanSelect(callsign));
}

extern "C" void* es_flightplan_correlated_radar_target(void* fp)
{
    return own(ES_AS(CFlightPlan, fp)->GetCorrelatedRadarTarget());
}

// --- CRadarTarget --------------------------------------------------------

extern "C" void es_radartarget_free(void* rt) { delete ES_AS(CRadarTarget, rt); }

extern "C" void* es_plugin_radartarget_select_first(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->RadarTargetSelectFirst());
}

extern "C" void* es_plugin_radartarget_select_next(void* plugin, void* current)
{
    return own(ES_AS(CPlugIn, plugin)->RadarTargetSelectNext(*ES_AS(CRadarTarget, current)));
}

extern "C" void* es_plugin_radartarget_select_asel(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->RadarTargetSelectASEL());
}

extern "C" void* es_plugin_radartarget_select(void* plugin, const char* callsign)
{
    return own(ES_AS(CPlugIn, plugin)->RadarTargetSelect(callsign));
}

extern "C" void* es_radartarget_correlated_flight_plan(void* rt)
{
    return own(ES_AS(CRadarTarget, rt)->GetCorrelatedFlightPlan());
}

// Owned CRadarTargetPositionData (latest, FP-track, and history walk).

extern "C" void* es_radartarget_current_position(void* rt)
{
    return own(ES_AS(CRadarTarget, rt)->GetPosition());
}

extern "C" void* es_radartarget_previous_position(void* rt, void* current)
{
    return own(ES_AS(CRadarTarget, rt)
                   ->GetPreviousPosition(*ES_AS(CRadarTargetPositionData, current)));
}

extern "C" void* es_flightplan_track_position(void* fp)
{
    return own(ES_AS(CFlightPlan, fp)->GetFPTrackPosition());
}

// --- CController ---------------------------------------------------------

extern "C" void es_controller_free(void* c) { delete ES_AS(CController, c); }

extern "C" void* es_plugin_controller_select_first(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->ControllerSelectFirst());
}

extern "C" void* es_plugin_controller_select_next(void* plugin, void* current)
{
    return own(ES_AS(CPlugIn, plugin)->ControllerSelectNext(*ES_AS(CController, current)));
}

extern "C" void* es_plugin_controller_select(void* plugin, const char* callsign)
{
    return own(ES_AS(CPlugIn, plugin)->ControllerSelect(callsign));
}

extern "C" void* es_plugin_controller_select_by_position_id(void* plugin, const char* position_id)
{
    return own(ES_AS(CPlugIn, plugin)->ControllerSelectByPositionId(position_id));
}

extern "C" void* es_plugin_controller_myself(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->ControllerMyself());
}

// --- Misc CPlugIn scalars & ASEL setters ---------------------------------

extern "C" int es_plugin_transition_altitude(void* plugin)
{
    return ES_AS(CPlugIn, plugin)->GetTransitionAltitude();
}

extern "C" void es_plugin_set_asel_flightplan(void* plugin, void* fp)
{
    ES_AS(CPlugIn, plugin)->SetASELAircraft(*ES_AS(CFlightPlan, fp));
}

extern "C" void es_plugin_set_asel_radartarget(void* plugin, void* rt)
{
    ES_AS(CPlugIn, plugin)->SetASELAircraft(*ES_AS(CRadarTarget, rt));
}

extern "C" const char* es_plugin_get_data_from_settings(void* plugin, const char* key)
{
    return ES_AS(CPlugIn, plugin)->GetDataFromSettings(key);
}

extern "C" void es_plugin_save_data_to_settings(void* plugin, const char* key,
                                                const char* description, const char* value)
{
    ES_AS(CPlugIn, plugin)->SaveDataToSettings(key, description, value);
}

// --- CFlightPlanList (RegisterFpList) ------------------------------------

extern "C" void es_fplist_free(void* list) { delete ES_AS(CFlightPlanList, list); }

extern "C" void* es_plugin_register_fp_list(void* plugin, const char* name)
{
    return own(ES_AS(CPlugIn, plugin)->RegisterFpList(name));
}

// --- CSectorElement (iteration, filtered by element type) ----------------

extern "C" void es_sectorelement_free(void* el) { delete ES_AS(CSectorElement, el); }

extern "C" void* es_plugin_sectorelement_select_first(void* plugin, int element_type)
{
    return own(ES_AS(CPlugIn, plugin)->SectorFileElementSelectFirst(element_type));
}

extern "C" void* es_plugin_sectorelement_select_next(void* plugin, void* current, int element_type)
{
    return own(ES_AS(CPlugIn, plugin)
                   ->SectorFileElementSelectNext(*ES_AS(CSectorElement, current), element_type));
}

// --- CGrountToAirChannel (iteration) -------------------------------------

extern "C" void es_gtachannel_free(void* ch) { delete ES_AS(CGrountToAirChannel, ch); }

extern "C" void* es_plugin_gtachannel_select_first(void* plugin)
{
    return own(ES_AS(CPlugIn, plugin)->GroundToArChannelSelectFirst());
}

extern "C" void* es_plugin_gtachannel_select_next(void* plugin, void* current)
{
    return own(ES_AS(CPlugIn, plugin)->GroundToArChannelSelectNext(*ES_AS(CGrountToAirChannel, current)));
}