use crate::ffi::StringBuffer;
use std::ffi::{CString, NulError};
use std::string::FromUtf8Error;
use xplm_sys::*;
pub mod borrowed;
pub mod owned;
pub enum ReadOnly {}
pub enum ReadWrite {}
pub trait Access {
fn writeable() -> bool;
}
impl Access for ReadOnly {
fn writeable() -> bool {
false
}
}
impl Access for ReadWrite {
fn writeable() -> bool {
true
}
}
pub trait DataRead<T> {
fn get(&self) -> T;
}
pub trait DataReadWrite<T>: DataRead<T> {
fn set(&mut self, value: T);
}
pub trait ArrayRead<T: ArrayType + ?Sized> {
fn get(&self, dest: &mut [T::Element]) -> usize;
fn len(&self) -> usize;
fn as_vec(&self) -> Vec<T::Element>
where
T::Element: Default + Clone,
{
let mut values = vec![T::Element::default(); self.len()];
self.get(&mut values);
values
}
}
pub trait ArrayReadWrite<T: ArrayType + ?Sized>: ArrayRead<T> {
fn set(&mut self, values: &[T::Element]);
}
pub trait StringRead {
fn get_to_string(&self, out: &mut String) -> Result<(), FromUtf8Error>;
fn get_as_string(&self) -> Result<String, FromUtf8Error>;
}
pub trait StringReadWrite: StringRead {
fn set_as_string(&mut self, value: &str) -> Result<(), NulError>;
}
impl<T> StringRead for T
where
T: ArrayRead<[u8]>,
{
fn get_to_string(&self, out: &mut String) -> Result<(), FromUtf8Error> {
let mut buffer = StringBuffer::new(self.len());
self.get(buffer.as_bytes_mut());
let value_string = buffer.into_string()?;
out.push_str(&value_string);
Ok(())
}
fn get_as_string(&self) -> Result<String, FromUtf8Error> {
let mut buffer = StringBuffer::new(self.len());
self.get(buffer.as_bytes_mut());
buffer.into_string()
}
}
impl<T> StringReadWrite for T
where
T: ArrayReadWrite<[u8]>,
{
fn set_as_string(&mut self, value: &str) -> Result<(), NulError> {
let name_c = CString::new(value)?;
self.set(name_c.as_bytes_with_nul());
Ok(())
}
}
pub trait DataType {
#[doc(hidden)]
type Storage: Sized;
#[doc(hidden)]
fn sim_type() -> XPLMDataTypeID;
#[doc(hidden)]
fn to_storage(&self) -> Self::Storage;
}
pub trait ArrayType: DataType {
type Element;
}
macro_rules! impl_type {
($native_type:ty as $sim_type:ident) => {
impl DataType for $native_type {
type Storage = Self;
fn sim_type() -> XPLMDataTypeID {
$sim_type as XPLMDataTypeID
}
fn to_storage(&self) -> Self::Storage {
self.clone()
}
}
};
([$native_type:ty]: array as $sim_type:ident) => {
impl DataType for [$native_type] {
type Storage = Vec<$native_type>;
fn sim_type() -> XPLMDataTypeID {
$sim_type as XPLMDataTypeID
}
fn to_storage(&self) -> Self::Storage {
self.to_vec()
}
}
impl ArrayType for [$native_type] {
type Element = $native_type;
}
};
}
impl_type!(bool as xplmType_Int);
impl_type!(u8 as xplmType_Int);
impl_type!(i8 as xplmType_Int);
impl_type!(u16 as xplmType_Int);
impl_type!(i16 as xplmType_Int);
impl_type!(u32 as xplmType_Int);
impl_type!(i32 as xplmType_Int);
impl_type!(f32 as xplmType_Float);
impl_type!(f64 as xplmType_Double);
impl_type!([i32]: array as xplmType_IntArray);
impl_type!([u32]: array as xplmType_IntArray);
impl_type!([f32]: array as xplmType_FloatArray);
impl_type!([u8]: array as xplmType_Data);
impl_type!([i8]: array as xplmType_Data);