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