use crate::bad_wire;
use crate::inventory::{Inventory, TypeId};
use crate::lang::types::{Type, TypeInfo, TypeKind, WireIO};
use crate::wire::SerializationError;
use std::io::{Read, Write};
use std::marker::PhantomData;
use std::mem::{ManuallyDrop, transmute};
pub unsafe trait CorrectSurrogate<T> {}
#[repr(transparent)]
pub struct Surrogate<T, L> {
inner: T,
_marker: PhantomData<L>,
}
unsafe impl<T, L: TypeInfo + CorrectSurrogate<T>> TypeInfo for Surrogate<T, L> {
const WIRE_SAFE: bool = false;
const RAW_SAFE: bool = L::RAW_SAFE;
const ASYNC_SAFE: bool = L::ASYNC_SAFE;
const SERVICE_SAFE: bool = L::SERVICE_SAFE;
const SERVICE_CTOR_SAFE: bool = L::SERVICE_CTOR_SAFE;
fn id() -> TypeId {
L::id()
}
fn kind() -> TypeKind {
L::kind()
}
fn ty() -> Type {
L::ty()
}
fn register(inventory: &mut impl Inventory) {
L::register(inventory);
}
}
unsafe impl<T, L: WireIO + CorrectSurrogate<T>> WireIO for Surrogate<T, L> {
fn write(&self, _: &mut impl Write) -> Result<(), SerializationError> {
bad_wire!()
}
fn read(_: &mut impl Read) -> Result<Self, SerializationError> {
bad_wire!()
}
fn live_size(&self) -> usize {
bad_wire!()
}
}
impl<T, L: TypeInfo + CorrectSurrogate<T>> Surrogate<T, L> {
pub const fn from_t(x: T) -> Self {
Self { inner: x, _marker: PhantomData }
}
pub fn from_l(x: L) -> Self {
let t = unsafe {
let this = ManuallyDrop::new(x);
std::ptr::read(std::ptr::from_ref::<L>(&*this).cast::<T>())
};
Self { inner: t, _marker: PhantomData }
}
pub const fn as_t(&self) -> &T {
&self.inner
}
pub fn as_t_mut(&mut self) -> &mut T {
&mut self.inner
}
#[allow(clippy::transmute_ptr_to_ptr)]
pub fn as_l(&self) -> &L {
unsafe { transmute(&self.inner) }
}
#[allow(clippy::transmute_ptr_to_ptr)]
pub fn as_l_mut(&mut self) -> &mut L {
unsafe { transmute(&mut self.inner) }
}
pub fn into_t(self) -> T {
self.inner
}
pub fn into_l(self) -> L {
unsafe {
let this = ManuallyDrop::new(self);
std::ptr::read(std::ptr::from_ref::<T>(&this.inner).cast::<L>())
}
}
}