Fix TCFType macros for generic types (#652)
* Improve TCFType macros This adds the following new features: * `declare_TCFType!`: Generics are accepted. * `impl_TCFType!`: Non-defaulted generics are accepted, and impls are fixed to be for all generics. In addition, some warnings are silenced and the macros no longer depend on any traits being in scope in the caller. * Support generics in impl_CFComparison * Add generic test for macros
This commit is contained in:
@@ -11,8 +11,6 @@
|
||||
|
||||
pub use core_foundation_sys::characterset::*;
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
declare_TCFType! {
|
||||
/// An immutable set of Unicode characters.
|
||||
CFCharacterSet, CFCharacterSetRef
|
||||
|
||||
+41
-18
@@ -53,15 +53,24 @@ macro_rules! declare_TCFType {
|
||||
$(#[$doc:meta])*
|
||||
$ty:ident, $raw:ident
|
||||
) => {
|
||||
$(#[$doc])*
|
||||
pub struct $ty($raw);
|
||||
declare_TCFType!($(#[$doc])* $ty<>, $raw);
|
||||
};
|
||||
|
||||
impl Drop for $ty {
|
||||
(
|
||||
$(#[$doc:meta])*
|
||||
$ty:ident<$($p:ident $(: $bound:path)*),*>, $raw:ident
|
||||
) => {
|
||||
$(#[$doc])*
|
||||
pub struct $ty<$($p $(: $bound)*),*>($raw, $(::std::marker::PhantomData<$p>),*);
|
||||
|
||||
#[allow(unused_imports)]
|
||||
impl<$($p $(: $bound)*),*> Drop for $ty<$($p),*> {
|
||||
fn drop(&mut self) {
|
||||
use $crate::base::TCFType;
|
||||
unsafe { $crate::base::CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Provide an implementation of the [`TCFType`] trait for the Rust
|
||||
@@ -82,6 +91,7 @@ macro_rules! impl_TCFType {
|
||||
impl<$($p $(: $bound)*),*> $crate::base::TCFType for $ty<$($p),*> {
|
||||
type Ref = $ty_ref;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[inline]
|
||||
fn as_concrete_TypeRef(&self) -> $ty_ref {
|
||||
self.0
|
||||
@@ -94,6 +104,7 @@ macro_rules! impl_TCFType {
|
||||
$crate::base::TCFType::wrap_under_create_rule(reference)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[inline]
|
||||
fn as_CFTypeRef(&self) -> $crate::base::CFTypeRef {
|
||||
self.as_concrete_TypeRef() as $crate::base::CFTypeRef
|
||||
@@ -115,39 +126,46 @@ macro_rules! impl_TCFType {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for $ty {
|
||||
#[allow(unused_imports)]
|
||||
impl<$($p $(: $bound)*),*> Clone for $ty<$($p),*> {
|
||||
#[inline]
|
||||
fn clone(&self) -> $ty {
|
||||
fn clone(&self) -> Self {
|
||||
use $crate::base::TCFType;
|
||||
unsafe {
|
||||
$ty::wrap_under_get_rule(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for $ty {
|
||||
#[allow(unused_imports)]
|
||||
impl<$($p $(: $bound)*),*> PartialEq for $ty<$($p),*> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$ty) -> bool {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
use $crate::base::TCFType;
|
||||
self.as_CFType().eq(&other.as_CFType())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $ty { }
|
||||
impl<$($p $(: $bound)*),*> Eq for $ty<$($p),*> { }
|
||||
|
||||
unsafe impl<'a> $crate::base::ToVoid<$ty> for &'a $ty {
|
||||
#[allow(unused_imports)]
|
||||
unsafe impl<'a, $($p $(: $bound)*),*> $crate::base::ToVoid<$ty<$($p),*>> for &'a $ty<$($p),*> {
|
||||
fn to_void(&self) -> *const ::core::ffi::c_void {
|
||||
use $crate::base::TCFTypeRef;
|
||||
use $crate::base::{TCFType, TCFTypeRef};
|
||||
self.as_concrete_TypeRef().as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::base::ToVoid<$ty> for $ty {
|
||||
#[allow(unused_imports)]
|
||||
unsafe impl<$($p $(: $bound)*),*> $crate::base::ToVoid<$ty<$($p),*>> for $ty<$($p),*> {
|
||||
fn to_void(&self) -> *const ::core::ffi::c_void {
|
||||
use $crate::base::TCFTypeRef;
|
||||
use $crate::base::{TCFType, TCFTypeRef};
|
||||
self.as_concrete_TypeRef().as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::base::ToVoid<$ty> for $ty_ref {
|
||||
#[allow(unused_imports)]
|
||||
unsafe impl<$($p $(: $bound)*),*> $crate::base::ToVoid<$ty<$($p),*>> for $ty_ref {
|
||||
fn to_void(&self) -> *const ::core::ffi::c_void {
|
||||
use $crate::base::TCFTypeRef;
|
||||
self.as_void_ptr()
|
||||
@@ -178,8 +196,10 @@ macro_rules! impl_CFTypeDescription {
|
||||
impl_CFTypeDescription!($ty<>);
|
||||
};
|
||||
($ty:ident<$($p:ident $(: $bound:path)*),*>) => {
|
||||
#[allow(unused_imports)]
|
||||
impl<$($p $(: $bound)*),*> ::std::fmt::Debug for $ty<$($p),*> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
use $crate::base::TCFType;
|
||||
self.as_CFType().fmt(f)
|
||||
}
|
||||
}
|
||||
@@ -189,9 +209,12 @@ macro_rules! impl_CFTypeDescription {
|
||||
#[macro_export]
|
||||
macro_rules! impl_CFComparison {
|
||||
($ty:ident, $compare:ident) => {
|
||||
impl PartialOrd for $ty {
|
||||
impl_CFComparison!($ty<>, $compare);
|
||||
};
|
||||
($ty:ident<$($p:ident $(: $bound:path)*),*>, $compare:ident) => {
|
||||
impl<$($p $(: $bound)*),*> PartialOrd for $ty<$($p),*> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &$ty) -> Option<::std::cmp::Ordering> {
|
||||
fn partial_cmp(&self, other: &$ty<$($p),*>) -> Option<::std::cmp::Ordering> {
|
||||
unsafe {
|
||||
Some(
|
||||
$compare(
|
||||
@@ -205,9 +228,9 @@ macro_rules! impl_CFComparison {
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $ty {
|
||||
impl<$($p $(: $bound)*),*> Ord for $ty<$($p),*> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &$ty) -> ::std::cmp::Ordering {
|
||||
fn cmp(&self, other: &$ty<$($p),*>) -> ::std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,3 +24,8 @@ declare_TCFType!(CFFooBar, CFFooBarRef);
|
||||
impl_TCFType!(CFFooBar, CFFooBarRef, CFFooBarGetTypeID);
|
||||
impl_CFTypeDescription!(CFFooBar);
|
||||
impl_CFComparison!(CFFooBar, fake_compare);
|
||||
|
||||
declare_TCFType!(CFGenericFooBar<T: Clone>, CFFooBarRef);
|
||||
impl_TCFType!(CFGenericFooBar<T: Clone>, CFFooBarRef, CFFooBarGetTypeID);
|
||||
impl_CFTypeDescription!(CFGenericFooBar<T: Clone>);
|
||||
impl_CFComparison!(CFGenericFooBar<T: Clone>, fake_compare);
|
||||
|
||||
Reference in New Issue
Block a user