physxx 0.3.1

Wrapper around the PhysX C++ API that aims to preserve the original API as much as possible.
Documentation
use std::{ffi::CString, path::Path, ptr::null_mut};

use crate::{PxAny, PxBaseRef, PxCookingRef, PxPhysicsRef};

#[derive(Clone, Copy)]
pub struct PxSerializationRegistryRef(*mut physx_sys::PxSerializationRegistry);
impl PxSerializationRegistryRef {
    pub fn new(physics: &PxPhysicsRef) -> Self {
        Self(unsafe { physx_sys::PxSerialization_createSerializationRegistry_mut(physics.0) })
    }
    pub fn complete(&self, collection: PxCollectionRef) {
        self.complete_full(collection, None, false)
    }
    pub fn complete_full(
        &self,
        collection: PxCollectionRef,
        except_for: Option<PxCollectionRef>,
        follow_joints: bool,
    ) {
        unsafe {
            physx_sys::PxSerialization_complete_mut(
                collection.0,
                self.0,
                except_for.map_or(null_mut(), |x| x.0),
                follow_joints,
            )
        }
    }
    pub fn is_serializable(
        &self,
        collection: PxCollectionRef,
        external_reference: Option<PxCollectionRef>,
    ) -> bool {
        unsafe {
            physx_sys::PxSerialization_isSerializable_mut(
                collection.0,
                self.0,
                external_reference.map_or(null_mut(), |x| x.0),
            )
        }
    }
    pub fn serialize_collection_to_xml(
        &self,
        out_stream: &PxDefaultMemoryOutputStream,
        collection: PxCollectionRef,
    ) -> bool {
        unsafe {
            physx_sys::PxSerialization_serializeCollectionToXml_mut(
                out_stream.0 as *mut physx_sys::PxOutputStream,
                collection.0,
                self.0,
                null_mut(),
                null_mut(),
                null_mut(),
            )
        }
    }
    pub fn serialize_collection_to_binary(
        &self,
        out_stream: &PxDefaultMemoryOutputStream,
        collection: PxCollectionRef,
        external_refs: Option<PxCollectionRef>,
        export_names: Option<bool>,
    ) -> bool {
        unsafe {
            physx_sys::PxSerialization_serializeCollectionToBinary_mut(
                out_stream.0 as *mut physx_sys::PxOutputStream,
                collection.0,
                self.0,
                external_refs.map(|x| x.0).unwrap_or(null_mut()),
                export_names.unwrap_or(false),
            )
        }
    }
    pub fn create_collection_from_xml(
        &self,
        input_data: &PxDefaultMemoryInputData,
        cooking: &PxCookingRef,
    ) -> Option<PxCollectionRef> {
        unsafe {
            let res = physx_sys::PxSerialization_createCollectionFromXml_mut(
                input_data.0 as *mut physx_sys::PxInputData,
                cooking.0,
                self.0,
                null_mut(),
                null_mut(),
                null_mut(),
            );
            if res.is_null() {
                None
            } else {
                Some(PxCollectionRef(res))
            }
        }
    }
    pub fn release(self) {
        unsafe { physx_sys::PxSerializationRegistry_release_mut(self.0) }
    }
}
unsafe impl Sync for PxSerializationRegistryRef {}
unsafe impl Send for PxSerializationRegistryRef {}

pub type PxSerialObjectId = usize;

#[derive(Clone, Copy)]
pub struct PxCollectionRef(pub(crate) *mut physx_sys::PxCollection);
impl PxCollectionRef {
    pub fn new() -> Self {
        Self(unsafe { physx_sys::phys_PxCreateCollection() })
    }
    pub fn add(&mut self, object: PxBaseRef) {
        self.add_with_serial_id(object, 0)
    }
    pub fn add_with_serial_id(&mut self, object: PxBaseRef, id: PxSerialObjectId) {
        unsafe { physx_sys::PxCollection_add_mut(self.0, object.0, id) }
    }
    pub fn get_objects(&self) -> Vec<(PxSerialObjectId, PxAny)> {
        let mut res = Vec::new();
        unsafe {
            let count = physx_sys::PxCollection_getNbObjects(self.0);
            for i in 0..count {
                let obj = physx_sys::PxCollection_getObject(self.0, i);
                let id = physx_sys::PxCollection_getId(self.0, obj);
                res.push((id, PxAny::from_obj(obj)));
            }
        }
        res
    }
    pub fn release(&mut self) {
        unsafe { physx_sys::PxCollection_release_mut(self.0) }
    }
}
unsafe impl Sync for PxCollectionRef {}
unsafe impl Send for PxCollectionRef {}

pub trait AsPxPtr<T> {
    fn as_px_ptr(&self) -> T;
}

pub struct PxDefaultMemoryOutputStream(pub(crate) *mut physx_sys::PxDefaultMemoryOutputStream);
impl PxDefaultMemoryOutputStream {
    pub fn new() -> Self {
        Self(unsafe {
            let foundation = physx_sys::phys_PxGetFoundation();
            let cb = physx_sys::PxFoundation_getAllocatorCallback_mut(foundation);
            physx_sys::PxDefaultMemoryOutputStream_new_alloc(cb)
        })
    }
    pub fn get_data(&self) -> Vec<u8> {
        unsafe {
            let data = physx_sys::PxDefaultMemoryOutputStream_getData(self.0);
            let size = physx_sys::PxDefaultMemoryOutputStream_getSize(self.0) as usize;
            let mut res = vec![0; size];
            std::ptr::copy_nonoverlapping(data, res.as_mut_ptr(), size);
            res
        }
    }
}
impl Drop for PxDefaultMemoryOutputStream {
    fn drop(&mut self) {
        unsafe { physx_sys::PxDefaultMemoryOutputStream_delete(self.0) }
    }
}
unsafe impl Sync for PxDefaultMemoryOutputStream {}
unsafe impl Send for PxDefaultMemoryOutputStream {}
impl AsPxPtr<*mut physx_sys::PxOutputStream> for PxDefaultMemoryOutputStream {
    fn as_px_ptr(&self) -> *mut physx_sys::PxOutputStream {
        self.0 as _
    }
}

pub struct PxDefaultMemoryInputData(pub(crate) *mut physx_sys::PxDefaultMemoryInputData, Vec<u8>);
impl PxDefaultMemoryInputData {
    pub fn new(mut data: Vec<u8>) -> Self {
        Self(
            unsafe {
                physx_sys::PxDefaultMemoryInputData_new_alloc(data.as_mut_ptr(), data.len() as u32)
            },
            data,
        )
    }
}
impl Drop for PxDefaultMemoryInputData {
    fn drop(&mut self) {
        unsafe { physx_sys::PxDefaultMemoryInputData_delete(self.0) }
    }
}
unsafe impl Sync for PxDefaultMemoryInputData {}
unsafe impl Send for PxDefaultMemoryInputData {}
impl AsPxPtr<*mut physx_sys::PxInputStream> for PxDefaultMemoryInputData {
    fn as_px_ptr(&self) -> *mut physx_sys::PxInputStream {
        self.0 as _
    }
}

pub struct PxDefaultFileOutputStream(pub(crate) *mut physx_sys::PxDefaultFileOutputStream);
impl PxDefaultFileOutputStream {
    pub fn new(name: impl AsRef<Path>) -> Self {
        Self(unsafe {
            let name = CString::new(name.as_ref().as_os_str().to_str().unwrap()).unwrap();
            physx_sys::PxDefaultFileOutputStream_new_alloc(name.as_ptr())
        })
    }
}
impl Drop for PxDefaultFileOutputStream {
    fn drop(&mut self) {
        unsafe { physx_sys::PxDefaultFileOutputStream_delete(self.0) }
    }
}
unsafe impl Sync for PxDefaultFileOutputStream {}
unsafe impl Send for PxDefaultFileOutputStream {}
impl AsPxPtr<*mut physx_sys::PxOutputStream> for PxDefaultFileOutputStream {
    fn as_px_ptr(&self) -> *mut physx_sys::PxOutputStream {
        self.0 as _
    }
}

pub struct PxDefaultFileInputData(pub(crate) *mut physx_sys::PxDefaultFileInputData);
impl PxDefaultFileInputData {
    pub fn new(name: impl AsRef<Path>) -> Self {
        Self(unsafe {
            let name = CString::new(name.as_ref().as_os_str().to_str().unwrap()).unwrap();
            physx_sys::PxDefaultFileInputData_new_alloc(name.as_ptr())
        })
    }
}
impl Drop for PxDefaultFileInputData {
    fn drop(&mut self) {
        unsafe { physx_sys::PxDefaultFileInputData_delete(self.0) }
    }
}
unsafe impl Sync for PxDefaultFileInputData {}
unsafe impl Send for PxDefaultFileInputData {}
impl AsPxPtr<*mut physx_sys::PxInputStream> for PxDefaultFileInputData {
    fn as_px_ptr(&self) -> *mut physx_sys::PxInputStream {
        self.0 as _
    }
}