use crate::inventory::{Inventory, TypeId};
use crate::lang::types::{Type, TypeInfo, TypeKind, WireIO};
use crate::wire::SerializationError;
#[repr(transparent)]
pub struct ServiceHandle<T>(*const T);
impl<T> Copy for ServiceHandle<T> {}
impl<T> Clone for ServiceHandle<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> core::fmt::Debug for ServiceHandle<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ServiceHandle").field(&self.0).finish()
}
}
impl<T> PartialEq for ServiceHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for ServiceHandle<T> {}
impl<T> core::hash::Hash for ServiceHandle<T> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
unsafe impl<T> Send for ServiceHandle<T> {}
unsafe impl<T> Sync for ServiceHandle<T> {}
impl<T> ServiceHandle<T> {
pub fn from_ptr(ptr: *const T) -> Self {
Self(ptr)
}
#[must_use]
pub fn as_ptr(self) -> *const T {
self.0
}
}
unsafe impl<T: TypeInfo> TypeInfo for ServiceHandle<T> {
const WIRE_SAFE: bool = false;
const RAW_SAFE: bool = false;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
<*const T as TypeInfo>::id()
}
fn kind() -> TypeKind {
<*const T as TypeInfo>::kind()
}
fn ty() -> Type {
<*const T as TypeInfo>::ty()
}
fn register(inventory: &mut impl Inventory) {
T::register(inventory);
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl<T: WireIO> WireIO for ServiceHandle<T> {
fn write(&self, _: &mut impl std::io::Write) -> Result<(), SerializationError> {
crate::bad_wire!()
}
fn read(_: &mut impl std::io::Read) -> Result<Self, SerializationError> {
crate::bad_wire!()
}
fn live_size(&self) -> usize {
crate::bad_wire!()
}
}
pub trait ServiceHandleMap<S>: Sized {
type Mapped<T>;
fn map_service_handle<T>(self, f: impl FnOnce(ServiceHandle<S>) -> T) -> Self::Mapped<T>;
}
impl<S> ServiceHandleMap<S> for ServiceHandle<S> {
type Mapped<T> = T;
#[inline]
fn map_service_handle<T>(self, f: impl FnOnce(Self) -> T) -> T {
f(self)
}
}
impl<Inner: ServiceHandleMap<S>, E, S> ServiceHandleMap<S> for crate::pattern::result::Result<Inner, E> {
type Mapped<T> = crate::pattern::result::Result<Inner::Mapped<T>, E>;
#[inline]
fn map_service_handle<T>(self, f: impl FnOnce(ServiceHandle<S>) -> T) -> Self::Mapped<T> {
match self {
Self::Ok(s) => crate::pattern::result::Result::Ok(s.map_service_handle(f)),
Self::Err(e) => crate::pattern::result::Result::Err(e),
Self::Panic => crate::pattern::result::Result::Panic,
Self::Null => crate::pattern::result::Result::Null,
}
}
}
impl<Inner: ServiceHandleMap<S>, S> ServiceHandleMap<S> for crate::pattern::option::Option<Inner> {
type Mapped<T> = crate::pattern::option::Option<Inner::Mapped<T>>;
#[inline]
fn map_service_handle<T>(self, f: impl FnOnce(ServiceHandle<S>) -> T) -> Self::Mapped<T> {
match self {
Self::Some(s) => crate::pattern::option::Option::Some(s.map_service_handle(f)),
Self::None => crate::pattern::option::Option::None,
}
}
}
pub trait ServiceAs<S> {
type FFI;
}
impl<S, E> ServiceAs<S> for crate::pattern::result::Result<S, E> {
type FFI = crate::pattern::result::Result<ServiceHandle<S>, E>;
}
impl<S> ServiceAs<S> for crate::pattern::option::Option<S> {
type FFI = crate::pattern::option::Option<ServiceHandle<S>>;
}
pub trait PluginService: Sized {
fn service_handle(&self) -> ServiceHandle<Self>;
fn into_service_handle(self) -> ServiceHandle<Self>;
}