use super::*;
pub use ffi::RetrieveDataType;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct DataHandle(pub ffi::DataHandle);
#[allow(missing_docs)]
impl DataHandle {
#[inline]
pub fn from_ffi(h: ffi::DataHandle) -> Self {
Self(h)
}
#[inline]
pub fn as_ffi(self) -> ffi::DataHandle {
self.0
}
#[inline]
pub fn is_valid(self) -> bool {
(self.0 & 0xFFFF_FFFF) != 0xFFFF_FFFF
}
#[inline]
pub fn invalid() -> Self {
Self(0x0000_0001_FFFF_FFFF)
}
pub fn try_from_ffi(h: ffi::DataHandle) -> Option<Self> {
let eh = Self::from_ffi(h);
eh.is_valid().then_some(eh)
}
pub fn try_to_ffi(self) -> Option<u64> {
self.is_valid().then(|| self.as_ffi())
}
pub fn read_from<T: Sized>(self, retrieve_data_type: ffi::RetrieveDataType) -> T {
let len = World::retrieve_data(self, retrieve_data_type, &mut []);
let elem_size = std::mem::size_of::<T>() as u32;
assert!(len == elem_size);
let mut data: T = unsafe { std::mem::zeroed::<T>() };
let data_slice = unsafe {
std::slice::from_raw_parts_mut(((&mut data) as *mut T).cast::<u8>(), len as usize)
};
let new_len = World::retrieve_data(self, retrieve_data_type, data_slice);
assert!(new_len == len);
data
}
pub fn read<T: Sized>(self) -> T {
self.read_from(ffi::RetrieveDataType::Output)
}
pub fn read_str_from(self, retrieve_data_type: ffi::RetrieveDataType) -> String {
std::str::from_utf8(&World::retrieve_data_vec(self, retrieve_data_type))
.unwrap_or_default()
.to_owned()
}
pub fn read_str(self) -> String {
self.read_str_from(ffi::RetrieveDataType::Output)
}
pub fn read_vec_from<T: Sized + Clone>(
self,
retrieve_data_type: ffi::RetrieveDataType,
) -> Vec<T> {
let len = World::retrieve_data(self, retrieve_data_type, &mut []);
let elem_size = std::mem::size_of::<T>() as u32;
assert!((len % elem_size) == 0);
let num_elements = len / elem_size;
let mut data: Vec<T> = vec![unsafe { std::mem::zeroed::<T>() }; num_elements as usize];
let data_slice =
unsafe { std::slice::from_raw_parts_mut(data.as_mut_ptr().cast::<u8>(), len as usize) };
let new_len = World::retrieve_data(self, retrieve_data_type, data_slice);
assert!(new_len == len);
data
}
pub fn read_vec<T: Sized + Clone>(self) -> Vec<T> {
self.read_vec_from(ffi::RetrieveDataType::Output)
}
}
impl DataHandle {}
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct WorldData {
id: DataHandle,
}
impl Drop for WorldData {
fn drop(&mut self) {
World::destroy_data(self.id);
}
}
impl Clone for WorldData {
fn clone(&self) -> Self {
World::retain_data(self.id);
Self { id: self.id }
}
}
impl WorldData {
pub fn create(create_data_type: ffi::CreateDataType, input_data: &[u8]) -> Self {
Self {
id: World::create_data(create_data_type, input_data),
}
}
pub fn create_struct<T: Sized>(create_data_type: ffi::CreateDataType, input_data: &T) -> Self {
let data_slice = unsafe {
std::slice::from_raw_parts(
(input_data as *const T).cast::<u8>(),
std::mem::size_of::<T>(),
)
};
Self {
id: World::create_data(create_data_type, data_slice),
}
}
pub fn create_formatted_text(input_data: &str) -> Self {
Self {
id: World::create_data(ffi::CreateDataType::FormattedText, input_data.as_bytes()),
}
}
pub fn create_render_module_data(module_dependency_name: &str, input_data: &[u8]) -> Self {
let raw_data = ffi::RawRenderModuleData {
module_dependency_name_ptr: module_dependency_name.as_ptr() as u32,
module_dependency_name_len: module_dependency_name.len() as u32,
static_data_ptr: input_data.as_ptr() as u32,
static_data_len: input_data.len() as u32,
};
Self::create_struct(ffi::CreateDataType::RenderModule, &raw_data)
}
pub fn create_audio_module_data(module_dependency_name: &str, input_data: &[u8]) -> Self {
let raw_data = ffi::RawAudioModuleData {
module_dependency_name_ptr: module_dependency_name.as_ptr() as u32,
module_dependency_name_len: module_dependency_name.len() as u32,
data_ptr: input_data.as_ptr() as u32,
data_len: input_data.len() as u32,
};
Self::create_struct(ffi::CreateDataType::AudioModule, &raw_data)
}
pub fn retrieve_data<T: Sized>(&self, t: ffi::RetrieveDataType) -> T {
self.id.read_from::<T>(t)
}
pub fn data_type(&self) -> ffi::WorldDataType {
self.retrieve_data(ffi::RetrieveDataType::WorldDataType)
}
#[inline]
pub fn get_data_handle(&self) -> DataHandle {
self.id
}
pub fn from_data_handle(handle: DataHandle) -> Self {
World::retain_data(handle);
Self { id: handle }
}
pub fn set_debug_name(&self, name: &str) {
World::set_data_debug_name(self.id, name);
}
pub fn debug_name(&self) -> String {
World::get_data_debug_name(self.id)
}
#[inline]
pub fn is_valid(&self) -> bool {
World::is_valid_data(self.id)
}
}
impl ValueConverterTrait<WorldData> for ValueConverter {
fn into_value(v: WorldData) -> Value {
let v = std::mem::ManuallyDrop::new(v);
let handle = v.get_data_handle();
<Self as ValueConverterTrait<DataHandle>>::into_value(handle)
}
fn from_value(v: &Value) -> WorldData {
WorldData::from_data_handle(<Self as ValueConverterTrait<DataHandle>>::from_value(v))
}
}
impl ValueConverterTrait<DataHandle> for ValueConverter {
fn into_value(v: DataHandle) -> Value {
Value::from_i64(v.0 as i64)
}
fn from_value(v: &Value) -> DataHandle {
DataHandle::from_ffi(v.as_i64() as u64)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct BinaryData {
pub(crate) data: WorldData,
}
impl BinaryData {
pub fn new(data: &[u8]) -> Self {
Self {
data: WorldData::create(ffi::CreateDataType::Binary, data),
}
}
}
impl ValueConverterTrait<BinaryData> for ValueConverter {
fn into_value(v: BinaryData) -> Value {
<Self as ValueConverterTrait<WorldData>>::into_value(v.data)
}
fn from_value(v: &Value) -> BinaryData {
BinaryData {
data: <Self as ValueConverterTrait<WorldData>>::from_value(v),
}
}
}