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
106
107
108
109
110
111
112
113
114
//! `CRadarTarget` — a reference to a live aircraft radar track.
use std::marker::PhantomData;
use euroscope_sys::EsHandle;
use crate::{FlightPlan, utils::cstr};
/// A reference to a radar target (a tracked aircraft).
///
/// A thin handle over EuroScope's `CRadarTarget`, valid only for the duration of
/// the callback / query block that delivered it (`'cb`).
#[derive(Clone, Copy)]
pub struct RadarTarget<'cb> {
raw: EsHandle,
_marker: PhantomData<&'cb ()>,
}
impl RadarTarget<'_> {
pub(crate) fn from_raw(raw: EsHandle) -> Self {
Self {
raw,
_marker: PhantomData,
}
}
/// The raw `CRadarTarget*`. Escape hatch for `euroscope-sys` calls not yet
/// wrapped here, and used to build sibling handles that share this pointer.
pub(crate) fn as_ptr(&self) -> EsHandle {
self.raw
}
/// Whether this handle references a live aircraft.
pub fn is_valid(&self) -> bool {
// SAFETY: `raw` is the pointer EuroScope handed us for this callback.
unsafe { euroscope_sys::es_radartarget_is_valid(self.raw) }
}
/// The aircraft callsign. Empty if the handle is invalid. Borrows
/// EuroScope-owned memory; valid for this callback only.
pub fn callsign(&self) -> &str {
// SAFETY: the SDK returns a borrowed NUL-terminated ANSI string, or
// null (guarded).
unsafe { cstr(euroscope_sys::es_radartarget_callsign(self.raw)) }
}
/// The system-assigned target ID. Stable across all instances since it is
/// generated from the callsign. Borrows EuroScope-owned memory.
pub fn system_id(&self) -> &str {
// SAFETY: the SDK returns a borrowed NUL-terminated ANSI string, or
// null (guarded).
unsafe { cstr(euroscope_sys::es_radartarget_system_id(self.raw)) }
}
/// Calculated vertical speed in feet/minute. Protocol-inaccurate; use only
/// for climb/descend/level tests.
pub fn vertical_speed(&self) -> i32 {
// SAFETY: `raw` is the pointer EuroScope handed us for this callback.
unsafe { euroscope_sys::es_radartarget_vertical_speed(self.raw) }
}
/// Calculated track direction in degrees.
pub fn track_heading(&self) -> f64 {
// SAFETY: `raw` is the pointer EuroScope handed us for this callback.
unsafe { euroscope_sys::es_radartarget_track_heading(self.raw) }
}
/// Ground speed in knots. Uses the plane-reported value, falling back to
/// the calculated one when that is zero.
pub fn gs(&self) -> i32 {
// SAFETY: `raw` is the pointer EuroScope handed us for this callback.
unsafe { euroscope_sys::es_radartarget_gs(self.raw) }
}
/// Correlate this radar target with `flight_plan`, returning whether it
/// succeeded. **Mutates EuroScope state**; afterwards you need not call the
/// reciprocal correlate on the flight plan.
pub fn correlate_with_flight_plan(&self, flight_plan: FlightPlan<'_>) -> bool {
// SAFETY: both `raw` and the flight-plan pointer are handles EuroScope
// handed us for this callback; the SDK copies the (pointer-sized)
// flight-plan handle by value.
unsafe {
euroscope_sys::es_radartarget_correlate_with_flight_plan(self.raw, flight_plan.as_ptr())
}
}
/// Uncorrelate this radar target from its flight plan. **Mutates EuroScope
/// state**; afterwards the system will never re-correlate it automatically.
pub fn uncorrelate(&self) {
// SAFETY: `raw` is the pointer EuroScope handed us for this callback.
unsafe { euroscope_sys::es_radartarget_uncorrelate(self.raw) }
}
/// The latest position snapshot of this target (owned). `None` if invalid.
pub fn position(&self) -> Option<crate::OwnedRadarTargetPosition> {
// SAFETY: `raw` valid for this callback; shim returns a heap copy or null.
crate::OwnedRadarTargetPosition::from_owned(unsafe {
euroscope_sys::es_radartarget_current_position(self.as_ptr())
})
}
/// Walk this target's position history, newest first (up to ~20 snapshots).
pub fn position_history(&self) -> crate::PositionHistory {
crate::PositionHistory::new(self.as_ptr())
}
/// The flight plan correlated with this radar target, if any (owned).
pub fn correlated_flight_plan(&self) -> Option<crate::OwnedFlightPlan> {
// SAFETY: `raw` valid for this callback; shim returns a heap copy or null.
crate::OwnedFlightPlan::from_owned(unsafe {
euroscope_sys::es_radartarget_correlated_flight_plan(self.as_ptr())
})
}
}