1use crate::ffi::StringBuffer;
2use std::ffi::{CString, NulError};
3use std::string::FromUtf8Error;
4use xplm_sys::*;
5
6pub mod borrowed;
8pub mod owned;
10
11pub enum ReadOnly {}
13
14pub enum ReadWrite {}
16
17pub trait Access {
19 fn writeable() -> bool;
21}
22
23impl Access for ReadOnly {
24 fn writeable() -> bool {
25 false
26 }
27}
28
29impl Access for ReadWrite {
30 fn writeable() -> bool {
31 true
32 }
33}
34
35pub trait DataRead<T> {
37 fn get(&self) -> T;
39}
40
41pub trait DataReadWrite<T>: DataRead<T> {
43 fn set(&mut self, value: T);
45}
46
47pub trait ArrayRead<T: ArrayType + ?Sized> {
49 fn get(&self, dest: &mut [T::Element]) -> usize;
61
62 fn len(&self) -> usize;
64
65 fn as_vec(&self) -> Vec<T::Element>
67 where
68 T::Element: Default + Clone,
69 {
70 let mut values = vec![T::Element::default(); self.len()];
71 self.get(&mut values);
72 values
73 }
74}
75
76pub trait ArrayReadWrite<T: ArrayType + ?Sized>: ArrayRead<T> {
78 fn set(&mut self, values: &[T::Element]);
86}
87
88pub trait StringRead {
90 fn get_to_string(&self, out: &mut String) -> Result<(), FromUtf8Error>;
96
97 fn get_as_string(&self) -> Result<String, FromUtf8Error>;
99}
100
101pub trait StringReadWrite: StringRead {
103 fn set_as_string(&mut self, value: &str) -> Result<(), NulError>;
107}
108
109impl<T> StringRead for T
110where
111 T: ArrayRead<[u8]>,
112{
113 fn get_to_string(&self, out: &mut String) -> Result<(), FromUtf8Error> {
114 let mut buffer = StringBuffer::new(self.len());
115 self.get(buffer.as_bytes_mut());
116 let value_string = buffer.into_string()?;
117 out.push_str(&value_string);
118 Ok(())
119 }
120 fn get_as_string(&self) -> Result<String, FromUtf8Error> {
121 let mut buffer = StringBuffer::new(self.len());
122 self.get(buffer.as_bytes_mut());
123 buffer.into_string()
124 }
125}
126
127impl<T> StringReadWrite for T
128where
129 T: ArrayReadWrite<[u8]>,
130{
131 fn set_as_string(&mut self, value: &str) -> Result<(), NulError> {
132 let name_c = CString::new(value)?;
133 self.set(name_c.as_bytes_with_nul());
134 Ok(())
135 }
136}
137
138pub trait DataType {
140 #[doc(hidden)]
143 type Storage: Sized;
144 #[doc(hidden)]
146 fn sim_type() -> XPLMDataTypeID;
147 #[doc(hidden)]
149 fn to_storage(&self) -> Self::Storage;
150}
151
152pub trait ArrayType: DataType {
154 type Element;
156}
157
158macro_rules! impl_type {
159 ($native_type:ty as $sim_type:ident) => {
160 impl DataType for $native_type {
161 type Storage = Self;
162 fn sim_type() -> XPLMDataTypeID {
163 $sim_type as XPLMDataTypeID
164 }
165 fn to_storage(&self) -> Self::Storage {
166 self.clone()
167 }
168 }
169 };
170 ([$native_type:ty]: array as $sim_type:ident) => {
171 impl DataType for [$native_type] {
172 type Storage = Vec<$native_type>;
173 fn sim_type() -> XPLMDataTypeID {
174 $sim_type as XPLMDataTypeID
175 }
176 fn to_storage(&self) -> Self::Storage {
177 self.to_vec()
178 }
179 }
180 impl ArrayType for [$native_type] {
181 type Element = $native_type;
182 }
183 };
184}
185
186impl_type!(bool as xplmType_Int);
187impl_type!(u8 as xplmType_Int);
188impl_type!(i8 as xplmType_Int);
189impl_type!(u16 as xplmType_Int);
190impl_type!(i16 as xplmType_Int);
191impl_type!(u32 as xplmType_Int);
192impl_type!(i32 as xplmType_Int);
193impl_type!(f32 as xplmType_Float);
194impl_type!(f64 as xplmType_Double);
195impl_type!([i32]: array as xplmType_IntArray);
196impl_type!([u32]: array as xplmType_IntArray);
197impl_type!([f32]: array as xplmType_FloatArray);
198impl_type!([u8]: array as xplmType_Data);
199impl_type!([i8]: array as xplmType_Data);