tm_rs/
api.rs

1use crate::registry::RegistryApi;
2use anymap::{any::Any, Map};
3use lazy_static::lazy_static;
4use std::{ffi::c_void, sync::RwLock};
5
6pub trait Api: Copy + Clone + Send + Sync + 'static {
7    type CType;
8    const NAME: &'static [u8];
9
10    fn new(api: *mut c_void) -> Self;
11}
12
13pub trait ApiWithCtx: Api {
14    type Ctx;
15    type ApiInstance: Copy + Clone;
16
17    fn wrap(self, ctx: *const Self::Ctx) -> Self::ApiInstance;
18}
19
20pub trait ApiWithCtxMut: ApiWithCtx {
21    type ApiInstanceMut: Copy + Clone;
22
23    fn wrap_mut(self, ctx: *mut Self::Ctx) -> Self::ApiInstanceMut;
24}
25
26lazy_static! {
27    static ref REGISTERED_APIS: RwLock<Map<dyn Any + Send + Sync>> = RwLock::new(Map::new());
28}
29
30#[inline]
31#[allow(clippy::missing_safety_doc)]
32pub unsafe fn register<A: Api>(reg: &mut RegistryApi) {
33    REGISTERED_APIS
34        .write()
35        .unwrap()
36        .insert(A::new(reg.get(A::NAME)));
37}
38
39#[inline]
40pub fn get<A: Api>() -> A {
41    *REGISTERED_APIS.read().unwrap().get::<A>().unwrap()
42}
43
44#[inline]
45pub fn with_ctx<A: ApiWithCtx>(ctx: *const A::Ctx) -> A::ApiInstance {
46    assert!(!ctx.is_null());
47    REGISTERED_APIS
48        .read()
49        .unwrap()
50        .get::<A>()
51        .unwrap()
52        .wrap(ctx)
53}
54
55#[inline]
56pub fn with_ctx_mut<A: ApiWithCtxMut>(ctx: *mut A::Ctx) -> A::ApiInstanceMut {
57    assert!(!ctx.is_null());
58    REGISTERED_APIS
59        .read()
60        .unwrap()
61        .get::<A>()
62        .unwrap()
63        .wrap_mut(ctx)
64}