tm_rs/
registry.rs

1use tm_sys::ffi::{
2    TM_ENTITY_CREATE_COMPONENT_INTERFACE_NAME, TM_THE_TRUTH_CREATE_TYPES_INTERFACE_NAME,
3};
4
5use crate::component::DerivedComponent;
6
7use super::ffi;
8use std::{ffi::c_void, os::raw::c_char};
9
10pub struct RegistryApi {
11    reg: *mut ffi::tm_api_registry_api,
12    load: bool,
13}
14
15impl RegistryApi {
16    #[allow(clippy::missing_safety_doc)]
17    pub unsafe fn new(reg: *mut ffi::tm_api_registry_api, load: bool) -> Self {
18        assert!(!reg.is_null());
19        Self { reg, load }
20    }
21
22    #[inline]
23    pub fn get(&mut self, name: &[u8]) -> *mut c_void {
24        unsafe { (*self.reg).get.unwrap()(name.as_ptr() as *const c_char) }
25    }
26
27    #[inline]
28    #[allow(clippy::missing_safety_doc)]
29    pub unsafe fn add_implementation(&mut self, name: &[u8], implementation: *mut c_void) {
30        assert!(!implementation.is_null());
31        (*self.reg).add_implementation.unwrap()(name.as_ptr() as *const c_char, implementation)
32    }
33
34    #[inline]
35    #[allow(clippy::missing_safety_doc)]
36    pub unsafe fn remove_implementation(&mut self, name: &[u8], implementation: *mut c_void) {
37        assert!(!implementation.is_null());
38        (*self.reg).remove_implementation.unwrap()(name.as_ptr() as *const c_char, implementation)
39    }
40
41    #[inline]
42    #[allow(clippy::missing_safety_doc)]
43    pub unsafe fn add_or_remove_implementation(&mut self, name: &[u8], ptr: *mut c_void) {
44        assert!(!ptr.is_null());
45
46        if self.load {
47            self.add_implementation(name, ptr);
48        } else {
49            self.remove_implementation(name, ptr);
50        }
51    }
52
53    pub fn add_or_remove_component<C: DerivedComponent>(&mut self) {
54        unsafe {
55            if let Some(create_types) = C::CREATE_TYPES {
56                self.add_or_remove_implementation(
57                    TM_THE_TRUTH_CREATE_TYPES_INTERFACE_NAME,
58                    create_types as *mut c_void,
59                );
60            }
61            self.add_or_remove_implementation(
62                TM_ENTITY_CREATE_COMPONENT_INTERFACE_NAME,
63                C::CREATE_COMPONENT as *mut c_void,
64            );
65        }
66    }
67}
68
69#[macro_export]
70macro_rules! add_or_remove_entity_simulation {
71    ($reg:expr, $name:ident) => {
72        $crate::paste::paste! {
73            unsafe extern "C" fn [<$name _extern>](ctx: *mut $crate::ffi::tm_entity_context_o) {
74                assert!(!ctx.is_null());
75
76                let mut entity_api = $crate::api::with_ctx_mut::<$crate::entity::EntityApi>(ctx);
77
78                $name(&mut entity_api);
79            }
80
81            $reg.add_or_remove_implementation(
82                $crate::ffi::TM_ENTITY_SIMULATION_INTERFACE_NAME,
83                [<$name _extern>] as *mut ::std::ffi::c_void,
84            );
85        }
86    };
87}