1use 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#[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#[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
107pub fn trigger_key_event(event_id: sys::ID32, value: sys::UINT32) {
109 unsafe {
110 sys::trigger_key_event(event_id, value);
111 }
112}
113
114pub 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
214pub 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#[derive(Debug)]
222pub struct CompiledCalculatorCode {
223 p_compiled: sys::PCSTRINGZ,
224 _p_compiled_size: sys::UINT32,
225}
226
227impl CompiledCalculatorCode {
228 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 pub fn execute<T: ExecuteCalculatorCodeImpl>(&self) -> Option<T> {
252 ExecuteCalculatorCodeImpl::execute(unsafe { std::ffi::CStr::from_ptr(self.p_compiled) })
253 }
254}