diff --git a/core-foundation/src/array.rs b/core-foundation/src/array.rs index 4b53048..3db2e93 100644 --- a/core-foundation/src/array.rs +++ b/core-foundation/src/array.rs @@ -100,8 +100,8 @@ impl<'a, T: FromVoid> ExactSizeIterator for CFArrayIterator<'a, T> { } } -impl_TCFTypeGeneric!(CFArray, CFArrayRef, CFArrayGetTypeID); -impl_CFTypeDescriptionGeneric!(CFArray); +impl_TCFType!(CFArray, CFArrayRef, CFArrayGetTypeID); +impl_CFTypeDescription!(CFArray); unsafe impl ConcreteCFType for CFArray<*const c_void> {} diff --git a/core-foundation/src/lib.rs b/core-foundation/src/lib.rs index fa1d8a3..ef9f53e 100644 --- a/core-foundation/src/lib.rs +++ b/core-foundation/src/lib.rs @@ -38,7 +38,12 @@ macro_rules! declare_TCFType { #[macro_export] macro_rules! impl_TCFType { ($ty:ident, $ty_ref:ident, $ty_id:ident) => { - impl $crate::base::TCFType for $ty { + impl_TCFType!($ty<>, $ty_ref, $ty_id); + unsafe impl $crate::ConcreteCFType for $ty { } + }; + + ($ty:ident<$($p:ident $(: $bound:path)*),*>, $ty_ref:ident, $ty_id:ident) => { + impl<$($p $(: $bound)*),*> $crate::base::TCFType for $ty<$($p),*> { type Ref = $ty_ref; #[inline] @@ -47,7 +52,7 @@ macro_rules! impl_TCFType { } #[inline] - unsafe fn wrap_under_get_rule(reference: $ty_ref) -> $ty { + unsafe fn wrap_under_get_rule(reference: $ty_ref) -> Self { use std::mem; let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference))); $crate::base::TCFType::wrap_under_create_rule(reference) @@ -61,8 +66,10 @@ macro_rules! impl_TCFType { } #[inline] - unsafe fn wrap_under_create_rule(reference: $ty_ref) -> $ty { - $ty(reference) + unsafe fn wrap_under_create_rule(reference: $ty_ref) -> Self { + // we need one PhantomData for each type parameter so call ourselves + // again with @Phantom $p to produce that + $ty(reference $(, impl_TCFType!(@Phantom $p))*) } #[inline] @@ -91,86 +98,20 @@ macro_rules! impl_TCFType { impl Eq for $ty { } - unsafe impl $crate::ConcreteCFType for $ty { } - } -} - -// This is basically identical to the implementation above. I can't -// think of a clean way to have them share code -#[macro_export] -macro_rules! impl_TCFTypeGeneric { - ($ty:ident, $ty_ref:ident, $ty_id:ident) => { - impl $crate::base::TCFType for $ty { - type Ref = $ty_ref; - - #[inline] - fn as_concrete_TypeRef(&self) -> $ty_ref { - self.0 - } - - #[inline] - unsafe fn wrap_under_get_rule(reference: $ty_ref) -> $ty { - use std::mem; - let reference = mem::transmute($crate::base::CFRetain(mem::transmute(reference))); - $crate::base::TCFType::wrap_under_create_rule(reference) - } + }; - #[inline] - fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef { - unsafe { - ::std::mem::transmute(self.as_concrete_TypeRef()) - } - } - - #[inline] - unsafe fn wrap_under_create_rule(obj: $ty_ref) -> $ty { - $ty(obj, PhantomData) - } - - #[inline] - fn type_id() -> ::core_foundation_sys::base::CFTypeID { - unsafe { - $ty_id() - } - } - } - - impl Clone for $ty { - #[inline] - fn clone(&self) -> $ty { - unsafe { - $ty::wrap_under_get_rule(self.0) - } - } - } - - impl PartialEq for $ty { - #[inline] - fn eq(&self, other: &$ty) -> bool { - self.as_CFType().eq(&other.as_CFType()) - } - } - - impl Eq for $ty { } - } + (@Phantom $x:ident) => { ::std::marker::PhantomData }; } -#[macro_export] -macro_rules! impl_CFTypeDescription { - ($ty:ident) => { - impl ::std::fmt::Debug for $ty { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - self.as_CFType().fmt(f) - } - } - } -} -// The same as impl_CFTypeDescription but with a type parameter #[macro_export] -macro_rules! impl_CFTypeDescriptionGeneric { +macro_rules! impl_CFTypeDescription { ($ty:ident) => { - impl ::std::fmt::Debug for $ty { + // it's fine to use an empty <> list + impl_CFTypeDescription!($ty<>); + }; + ($ty:ident<$($p:ident $(: $bound:path)*),*>) => { + impl<$($p $(: $bound)*),*> ::std::fmt::Debug for $ty<$($p),*> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { self.as_CFType().fmt(f) }