msfs/
legacy.rs

1//! Bindings to the Legacy/gauges.h API
2
3use crate::sys;
4
5#[doc(hidden)]
6pub trait SimVarF64 {
7    fn to(self) -> f64;
8    fn from(v: f64) -> Self;
9}
10
11impl SimVarF64 for f64 {
12    fn to(self) -> f64 {
13        self
14    }
15
16    fn from(v: f64) -> Self {
17        v
18    }
19}
20
21impl SimVarF64 for bool {
22    fn to(self) -> f64 {
23        if self { 1.0 } else { 0.0 }
24    }
25
26    fn from(v: f64) -> Self {
27        v != 0.0
28    }
29}
30
31impl SimVarF64 for u8 {
32    fn to(self) -> f64 {
33        self as f64
34    }
35
36    fn from(v: f64) -> Self {
37        v as Self
38    }
39}
40
41/// aircraft_varget
42/// get_aircraft_var_enum
43#[derive(Debug)]
44pub struct AircraftVariable {
45    simvar: sys::ENUM,
46    units: sys::ENUM,
47    index: sys::SINT32,
48}
49impl AircraftVariable {
50    pub fn from(name: &str, units: &str, index: usize) -> Result<Self, Box<dyn std::error::Error>> {
51        let name = std::ffi::CString::new(name).unwrap();
52        let units = std::ffi::CString::new(units).unwrap();
53
54        let simvar = unsafe { sys::get_aircraft_var_enum(name.as_ptr()) };
55        if simvar == -1 {
56            return Err(Box::new(std::io::Error::new(
57                std::io::ErrorKind::Other,
58                "invalid name",
59            )));
60        }
61
62        let units = unsafe { sys::get_units_enum(units.as_ptr()) };
63        if units == -1 {
64            return Err(Box::new(std::io::Error::new(
65                std::io::ErrorKind::Other,
66                "invalid units",
67            )));
68        }
69        Ok(Self {
70            simvar,
71            units,
72            index: index as sys::SINT32,
73        })
74    }
75
76    pub fn get<T: SimVarF64>(&self) -> T {
77        let v = unsafe { sys::aircraft_varget(self.simvar, self.units, self.index) };
78        T::from(v)
79    }
80}
81
82/// register_named_variable
83/// set_named_variable_typed_value
84/// get_named_variable_value
85/// set_named_variable_value
86#[derive(Debug)]
87pub struct NamedVariable(sys::ID);
88impl NamedVariable {
89    pub fn from(name: &str) -> Self {
90        Self(unsafe {
91            let name = std::ffi::CString::new(name).unwrap();
92            sys::register_named_variable(name.as_ptr())
93        })
94    }
95
96    pub fn get_value<T: SimVarF64>(&self) -> T {
97        let v = unsafe { sys::get_named_variable_value(self.0) };
98        T::from(v)
99    }
100
101    pub fn set_value(&self, v: impl SimVarF64) {
102        let v = v.to();
103        unsafe { sys::set_named_variable_value(self.0, v) }
104    }
105}
106
107/// trigger_key_event
108pub fn trigger_key_event(event_id: sys::ID32, value: sys::UINT32) {
109    unsafe {
110        sys::trigger_key_event(event_id, value);
111    }
112}
113
114/// trigger_key_event_EX1
115pub fn trigger_key_event_ex1(
116    event_id: sys::ID32,
117    value0: sys::UINT32,
118    value1: sys::UINT32,
119    value2: sys::UINT32,
120    value3: sys::UINT32,
121    value4: sys::UINT32,
122) {
123    unsafe {
124        sys::trigger_key_event_EX1(event_id, value0, value1, value2, value3, value4);
125    }
126}
127
128#[doc(hidden)]
129pub trait ExecuteCalculatorCodeImpl {
130    fn execute(code: &std::ffi::CStr) -> Option<Self>
131    where
132        Self: Sized;
133}
134
135#[doc(hidden)]
136impl ExecuteCalculatorCodeImpl for f64 {
137    fn execute(code: &std::ffi::CStr) -> Option<Self> {
138        unsafe {
139            let mut n = 0.0;
140            if sys::execute_calculator_code(
141                code.as_ptr(),
142                &mut n,
143                std::ptr::null_mut(),
144                std::ptr::null_mut(),
145            ) == 1
146            {
147                Some(n)
148            } else {
149                None
150            }
151        }
152    }
153}
154
155#[doc(hidden)]
156impl ExecuteCalculatorCodeImpl for i32 {
157    fn execute(code: &std::ffi::CStr) -> Option<Self> {
158        unsafe {
159            let mut n = 0;
160            if sys::execute_calculator_code(
161                code.as_ptr(),
162                std::ptr::null_mut(),
163                &mut n,
164                std::ptr::null_mut(),
165            ) == 1
166            {
167                Some(n)
168            } else {
169                None
170            }
171        }
172    }
173}
174
175#[doc(hidden)]
176impl ExecuteCalculatorCodeImpl for String {
177    fn execute(code: &std::ffi::CStr) -> Option<Self> {
178        unsafe {
179            let mut s = std::ptr::null();
180            if sys::execute_calculator_code(
181                code.as_ptr(),
182                std::ptr::null_mut(),
183                std::ptr::null_mut(),
184                &mut s,
185            ) == 1
186            {
187                Some(std::ffi::CStr::from_ptr(s).to_str().unwrap().to_owned())
188            } else {
189                None
190            }
191        }
192    }
193}
194
195#[doc(hidden)]
196impl ExecuteCalculatorCodeImpl for () {
197    fn execute(code: &std::ffi::CStr) -> Option<Self> {
198        unsafe {
199            if sys::execute_calculator_code(
200                code.as_ptr(),
201                std::ptr::null_mut(),
202                std::ptr::null_mut(),
203                std::ptr::null_mut(),
204            ) == 1
205            {
206                Some(())
207            } else {
208                None
209            }
210        }
211    }
212}
213
214/// execute_calculator_code
215pub fn execute_calculator_code<T: ExecuteCalculatorCodeImpl>(code: &str) -> Option<T> {
216    let code = std::ffi::CString::new(code).unwrap();
217    ExecuteCalculatorCodeImpl::execute(code.as_c_str())
218}
219
220/// Holds compiled calculator code, wraps `gauge_calculator_code_precompile`.
221#[derive(Debug)]
222pub struct CompiledCalculatorCode {
223    p_compiled: sys::PCSTRINGZ,
224    _p_compiled_size: sys::UINT32,
225}
226
227impl CompiledCalculatorCode {
228    /// Create a new CompiledCalculatorCode instance.
229    pub fn new(code: &str) -> Option<Self> {
230        let mut p_compiled = std::mem::MaybeUninit::uninit();
231        let mut p_compiled_size = std::mem::MaybeUninit::uninit();
232        unsafe {
233            let code = std::ffi::CString::new(code).unwrap();
234            if sys::gauge_calculator_code_precompile(
235                p_compiled.as_mut_ptr(),
236                p_compiled_size.as_mut_ptr(),
237                code.as_ptr(),
238            ) != 0
239            {
240                Some(CompiledCalculatorCode {
241                    p_compiled: p_compiled.assume_init(),
242                    _p_compiled_size: p_compiled_size.assume_init(),
243                })
244            } else {
245                None
246            }
247        }
248    }
249
250    /// Execute this CompiledCalculatorCode instance.
251    pub fn execute<T: ExecuteCalculatorCodeImpl>(&self) -> Option<T> {
252        ExecuteCalculatorCodeImpl::execute(unsafe { std::ffi::CStr::from_ptr(self.p_compiled) })
253    }
254}