use crate::prelude::*;
use crate::ComItf;
#[derive(Debug, Clone, Copy, Hash, PartialOrd, PartialEq, Eq)]
#[repr(C)]
pub enum TypeSystemName
{
Automation = 0,
Raw = 1,
}
impl TypeSystemName
{
pub fn get_ptr<I: ?Sized>(self, itf: &ComItf<I>) -> crate::raw::RawComPtr
{
let opt = match self {
TypeSystemName::Automation => AutomationTypeSystem::get_ptr(itf).map(|p| p.ptr),
TypeSystemName::Raw => RawTypeSystem::get_ptr(itf).map(|p| p.ptr),
};
match opt {
Some(ptr) => ptr.as_ptr(),
None => std::ptr::null_mut(),
}
}
}
pub trait TypeSystem: Clone + Copy
{
const AUTOMATION: TypeSystemName = TypeSystemName::Automation;
const RAW: TypeSystemName = TypeSystemName::Raw;
fn key() -> TypeSystemName;
fn get_ptr<I: ?Sized>(itf: &ComItf<I>) -> Option<crate::raw::InterfacePtr<Self, I>>;
fn wrap_ptr<I: ?Sized>(ptr: crate::raw::InterfacePtr<Self, I>) -> ComItf<I>;
}
#[derive(Clone, Copy)]
pub struct AutomationTypeSystem;
impl TypeSystem for AutomationTypeSystem
{
fn key() -> TypeSystemName
{
TypeSystemName::Automation
}
fn get_ptr<I: ?Sized>(itf: &ComItf<I>) -> Option<crate::raw::InterfacePtr<Self, I>>
{
itf.automation_ptr
}
fn wrap_ptr<I: ?Sized>(ptr: crate::raw::InterfacePtr<Self, I>) -> ComItf<I>
{
ComItf {
automation_ptr: Some(ptr),
raw_ptr: None,
phantom: std::marker::PhantomData,
}
}
}
#[derive(Clone, Copy)]
pub struct RawTypeSystem;
impl TypeSystem for RawTypeSystem
{
fn key() -> TypeSystemName
{
TypeSystemName::Raw
}
fn get_ptr<I: ?Sized>(itf: &ComItf<I>) -> Option<crate::raw::InterfacePtr<Self, I>>
{
itf.raw_ptr
}
fn wrap_ptr<I: ?Sized>(ptr: crate::raw::InterfacePtr<Self, I>) -> ComItf<I>
{
ComItf {
automation_ptr: None,
raw_ptr: Some(ptr),
phantom: std::marker::PhantomData,
}
}
}
pub trait ForeignType
{
fn type_name() -> &'static str;
fn indirection_level() -> u32
{
0
}
}
pub trait ExternType<TS: TypeSystem>
{
type ForeignType: ForeignType;
}
pub unsafe trait ExternInput<TS: TypeSystem>: ExternType<TS> + Sized
{
type Lease;
unsafe fn into_foreign_parameter(self) -> ComResult<(Self::ForeignType, Self::Lease)>;
type Owned;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> ComResult<Self::Owned>;
}
pub unsafe trait ExternOutput<TS: TypeSystem>: ExternType<TS> + Sized
{
fn into_foreign_output(self) -> ComResult<Self::ForeignType>;
unsafe fn from_foreign_output(source: Self::ForeignType) -> ComResult<Self>;
unsafe fn drop_foreign_output(source: Self::ForeignType)
{
let _ = Self::from_foreign_output(source);
}
}
pub unsafe trait InfallibleExternInput<TS: TypeSystem>: ExternType<TS> + Sized
{
type Lease;
unsafe fn into_foreign_parameter(self) -> (Self::ForeignType, Self::Lease);
type Owned;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> Self::Owned;
}
pub unsafe trait InfallibleExternOutput<TS: TypeSystem>: ExternType<TS> + Sized
{
fn into_foreign_output(self) -> Self::ForeignType;
unsafe fn from_foreign_output(source: Self::ForeignType) -> Self;
}
pub struct OutputGuard<TS, TType>
where
TS: TypeSystem,
TType: ExternOutput<TS>,
{
value: std::mem::ManuallyDrop<TType::ForeignType>,
}
impl<TS, TType> OutputGuard<TS, TType>
where
TS: TypeSystem,
TType: ExternOutput<TS>,
{
pub fn wrap(value: TType::ForeignType) -> OutputGuard<TS, TType>
{
OutputGuard {
value: std::mem::ManuallyDrop::new(value),
}
}
pub fn consume(self) -> TType::ForeignType
{
unsafe {
let value = std::ptr::read(&self.value);
std::mem::forget(self);
std::mem::ManuallyDrop::into_inner(value)
}
}
}
impl<TS, TType> Drop for OutputGuard<TS, TType>
where
TS: TypeSystem,
TType: ExternOutput<TS>,
{
fn drop(&mut self)
{
unsafe {
let v = std::mem::ManuallyDrop::take(&mut self.value);
TType::drop_foreign_output(v);
}
}
}
macro_rules! self_extern {
( $t:ty ) => {
impl ForeignType for $t
{
fn type_name() -> &'static str
{
stringify!($t)
}
}
impl<TS: TypeSystem> ExternType<TS> for $t
{
type ForeignType = $t;
}
unsafe impl<TS: TypeSystem> ExternInput<TS> for $t
{
type Lease = ();
unsafe fn into_foreign_parameter(self) -> ComResult<(Self::ForeignType, ())>
{
Ok((self, ()))
}
type Owned = Self;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> ComResult<Self::Owned>
{
Ok(source)
}
}
unsafe impl<TS: TypeSystem> ExternOutput<TS> for $t
{
fn into_foreign_output(self) -> ComResult<Self::ForeignType>
{
Ok(self)
}
unsafe fn from_foreign_output(source: Self::ForeignType) -> ComResult<Self>
{
Ok(source)
}
}
unsafe impl<TS: TypeSystem> InfallibleExternInput<TS> for $t
{
type Lease = ();
unsafe fn into_foreign_parameter(self) -> (Self::ForeignType, ())
{
(self, ())
}
type Owned = Self;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> Self::Owned
{
source
}
}
unsafe impl<TS: TypeSystem> InfallibleExternOutput<TS> for $t
{
fn into_foreign_output(self) -> Self::ForeignType
{
self
}
unsafe fn from_foreign_output(source: Self::ForeignType) -> Self
{
source
}
}
};
}
self_extern!(());
self_extern!(i8);
self_extern!(i16);
self_extern!(i32);
self_extern!(i64);
self_extern!(isize);
self_extern!(u8);
self_extern!(u16);
self_extern!(u32);
self_extern!(u64);
self_extern!(usize);
self_extern!(f32);
self_extern!(f64);
self_extern!(bool);
use crate::raw::HRESULT;
self_extern!(HRESULT);
use crate::GUID;
self_extern!(GUID);
self_extern!(TypeSystemName);
self_extern!(std::ffi::c_void);
macro_rules! extern_ptr {
( $mut:tt ) => {
impl<TS: TypeSystem, TPtr: ForeignType + ?Sized> ExternType<TS> for *$mut TPtr
{
type ForeignType = Self;
}
unsafe impl<TS: TypeSystem, TPtr: ForeignType + ?Sized> ExternOutput<TS> for *$mut TPtr
{
fn into_foreign_output(self) -> ComResult<Self::ForeignType>
{
Ok(self)
}
unsafe fn from_foreign_output(source: Self::ForeignType) -> ComResult<Self>
{
Ok(source)
}
}
unsafe impl<TS: TypeSystem, TPtr: ForeignType + ?Sized> ExternInput<TS> for *$mut TPtr
{
type Lease = ();
unsafe fn into_foreign_parameter(self) -> ComResult<(Self::ForeignType, ())>
{
Ok((self, ()))
}
type Owned = Self;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> ComResult<Self::Owned>
{
Ok(source)
}
}
unsafe impl<TS: TypeSystem, TPtr: ForeignType + ?Sized> InfallibleExternOutput<TS> for *$mut TPtr
{
fn into_foreign_output(self) -> Self::ForeignType
{
self
}
unsafe fn from_foreign_output(source: Self::ForeignType) -> Self
{
source
}
}
unsafe impl<TS: TypeSystem, TPtr: ForeignType + ?Sized> InfallibleExternInput<TS> for *$mut TPtr
{
type Lease = ();
unsafe fn into_foreign_parameter(self) -> (Self::ForeignType, ())
{
(self, ())
}
type Owned = Self;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> Self::Owned
{
source
}
}
impl<TPtr: ForeignType + ?Sized> ForeignType for *$mut TPtr
{
fn type_name() -> &'static str
{
<TPtr as ForeignType>::type_name()
}
fn indirection_level() -> u32
{
<TPtr as ForeignType>::indirection_level() + 1
}
}
}
}
extern_ptr!(mut);
extern_ptr!(const);
pub trait ExternDefault
{
unsafe fn extern_default() -> Self;
}
impl<T> ExternDefault for T
{
unsafe fn extern_default() -> Self
{
std::mem::zeroed()
}
}