Skip to content

Commit 93c9cba

Browse files
committed
Change ConcreteTypeRef to an associated value
1 parent c2e5cce commit 93c9cba

File tree

6 files changed

+79
-41
lines changed

6 files changed

+79
-41
lines changed

core-foundation/src/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl_CFTypeDescriptionGeneric!(CFArray);
8383

8484
impl<T> CFArray<T> {
8585
/// Creates a new `CFArray` with the given elements, which must be `CFType` objects.
86-
pub fn from_CFTypes<R>(elems: &[T]) -> CFArray<T> where T: TCFType<R> {
86+
pub fn from_CFTypes(elems: &[T]) -> CFArray<T> where T: TCFType {
8787
unsafe {
8888
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
8989
let array_ref = CFArrayCreate(kCFAllocatorDefault,

core-foundation/src/base.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,20 @@ impl CFAllocator {
9191
}
9292
}
9393

94+
9495
/// All Core Foundation types implement this trait. The type parameter `TypeRef` specifies the
9596
/// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is
9697
/// `CFArrayRef`.
97-
pub trait TCFType<ConcreteTypeRef> {
98+
pub trait TCFType {
99+
/// The reference type wrapped inside this type.
100+
type ConcreteTypeRef: TCFReference;
101+
98102
/// Returns the object as its concrete TypeRef.
99-
fn as_concrete_TypeRef(&self) -> ConcreteTypeRef;
103+
fn as_concrete_TypeRef(&self) -> Self::ConcreteTypeRef;
100104

101105
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
102106
/// when following Core Foundation's "Create Rule". The reference count is *not* bumped.
103-
unsafe fn wrap_under_create_rule(obj: ConcreteTypeRef) -> Self;
107+
unsafe fn wrap_under_create_rule(obj: Self::ConcreteTypeRef) -> Self;
104108

105109
/// Returns the type ID for this class.
106110
fn type_id() -> CFTypeID;
@@ -118,7 +122,7 @@ pub trait TCFType<ConcreteTypeRef> {
118122

119123
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
120124
/// when following Core Foundation's "Get Rule". The reference count *is* bumped.
121-
unsafe fn wrap_under_get_rule(reference: ConcreteTypeRef) -> Self;
125+
unsafe fn wrap_under_get_rule(reference: Self::ConcreteTypeRef) -> Self;
122126

123127
/// Returns the reference count of the object. It is unwise to do anything other than test
124128
/// whether the return value of this method is greater than zero.
@@ -146,12 +150,14 @@ pub trait TCFType<ConcreteTypeRef> {
146150

147151
/// Returns true if this value is an instance of another type.
148152
#[inline]
149-
fn instance_of<OtherConcreteTypeRef,OtherCFType:TCFType<OtherConcreteTypeRef>>(&self) -> bool {
150-
self.type_of() == <OtherCFType as TCFType<_>>::type_id()
153+
fn instance_of<OtherCFType: TCFType>(&self) -> bool {
154+
self.type_of() == <OtherCFType as TCFType>::type_id()
151155
}
152156
}
153157

154-
impl TCFType<CFTypeRef> for CFType {
158+
impl TCFType for CFType {
159+
type ConcreteTypeRef = CFTypeRef;
160+
155161
#[inline]
156162
fn as_concrete_TypeRef(&self) -> CFTypeRef {
157163
self.0
@@ -180,7 +186,7 @@ impl TCFType<CFTypeRef> for CFType {
180186
}
181187

182188
#[inline]
183-
fn instance_of<OtherConcreteTypeRef,OtherCFType:TCFType<OtherConcreteTypeRef>>(&self) -> bool {
189+
fn instance_of<OtherCFType: TCFType>(&self) -> bool {
184190
// Since this is the root of the type hierarchy, we always answer yes.
185191
true
186192
}

core-foundation/src/dictionary.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use libc::c_void;
1616
use std::mem;
1717
use std::ptr;
1818

19-
use base::{CFType, CFIndexConvertible, TCFType};
19+
use base::{CFType, CFIndexConvertible, TCFType, TCFReference};
2020

2121
/// An immutable dictionary of key-value pairs.
2222
pub struct CFDictionary(CFDictionaryRef);
@@ -33,8 +33,8 @@ impl_TCFType!(CFDictionary, CFDictionaryRef, CFDictionaryGetTypeID);
3333
impl_CFTypeDescription!(CFDictionary);
3434

3535
impl CFDictionary {
36-
pub fn from_CFType_pairs<R1, R2, K, V>(pairs: &[(K, V)]) -> CFDictionary
37-
where K: TCFType<R1>, V: TCFType<R2> {
36+
pub fn from_CFType_pairs<K, V>(pairs: &[(K, V)]) -> CFDictionary
37+
where K: TCFType, V: TCFType {
3838
let (keys, values): (Vec<CFTypeRef>,Vec<CFTypeRef>) =
3939
pairs.iter()
4040
.map(|&(ref key, ref value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
@@ -73,8 +73,8 @@ impl CFDictionary {
7373
/// Similar to `contains_key` but acts on a higher level, automatically converting from any
7474
/// `TCFType` to the raw pointer of its concrete TypeRef.
7575
#[inline]
76-
pub fn contains_key2<X, K: TCFType<*const X>>(&self, key: &K) -> bool {
77-
self.contains_key(key.as_concrete_TypeRef() as *const c_void)
76+
pub fn contains_key2<K: TCFType>(&self, key: &K) -> bool {
77+
self.contains_key(key.as_concrete_TypeRef().as_void_ptr())
7878
}
7979

8080
#[inline]
@@ -92,8 +92,8 @@ impl CFDictionary {
9292
/// Similar to `find` but acts on a higher level, automatically converting from any `TCFType`
9393
/// to the raw pointer of its concrete TypeRef.
9494
#[inline]
95-
pub fn find2<X, K: TCFType<*const X>>(&self, key: &K) -> Option<*const c_void> {
96-
self.find(key.as_concrete_TypeRef() as *const c_void)
95+
pub fn find2<K: TCFType>(&self, key: &K) -> Option<*const c_void> {
96+
self.find(key.as_concrete_TypeRef().as_void_ptr())
9797
}
9898

9999
/// # Panics
@@ -131,3 +131,30 @@ impl CFDictionary {
131131
(keys, values)
132132
}
133133
}
134+
135+
136+
#[cfg(test)]
137+
pub mod test {
138+
use super::*;
139+
use ::string::CFString;
140+
use ::boolean::{CFBoolean, CFBooleanRef};
141+
142+
#[test]
143+
fn dict_find2_and_contains_key2() {
144+
let dict = CFDictionary::from_CFType_pairs(&[
145+
(
146+
CFString::from_static_string("hello"),
147+
CFBoolean::true_value(),
148+
),
149+
]);
150+
let key = CFString::from_static_string("hello");
151+
let invalid_key = CFString::from_static_string("foobar");
152+
153+
assert!(dict.contains_key2(&key));
154+
assert!(!dict.contains_key2(&invalid_key));
155+
156+
let value = unsafe { CFBoolean::wrap_under_get_rule(dict.find2(&key).unwrap() as CFBooleanRef) };
157+
assert_eq!(value, CFBoolean::true_value());
158+
assert_eq!(dict.find2(&invalid_key), None);
159+
}
160+
}

core-foundation/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ extern crate chrono;
1717
#[macro_export]
1818
macro_rules! impl_TCFType {
1919
($ty:ident, $raw:ident, $ty_id:ident) => {
20-
impl $crate::base::TCFType<$raw> for $ty {
20+
impl $crate::base::TCFType for $ty {
21+
type ConcreteTypeRef = $raw;
22+
2123
#[inline]
2224
fn as_concrete_TypeRef(&self) -> $raw {
2325
self.0
@@ -74,7 +76,9 @@ macro_rules! impl_TCFType {
7476
#[macro_export]
7577
macro_rules! impl_TCFTypeGeneric {
7678
($ty:ident, $raw:ident, $ty_id:ident) => {
77-
impl<T> $crate::base::TCFType<$raw> for $ty<T> {
79+
impl<T> $crate::base::TCFType for $ty<T> {
80+
type ConcreteTypeRef = $raw;
81+
7882
#[inline]
7983
fn as_concrete_TypeRef(&self) -> $raw {
8084
self.0

core-foundation/src/propertylist.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use libc::c_void;
1616

1717
use error::CFError;
1818
use data::CFData;
19-
use base::{CFType, TCFType};
19+
use base::{CFType, TCFType, TCFReference};
2020

2121
pub use core_foundation_sys::propertylist::*;
2222
use core_foundation_sys::error::CFErrorRef;
@@ -62,22 +62,22 @@ pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -
6262
/// Trait for all subclasses of [`CFPropertyList`].
6363
///
6464
/// [`CFPropertyList`]: struct.CFPropertyList.html
65-
pub trait CFPropertyListSubClass<Raw>: TCFType<*const Raw> {
65+
pub trait CFPropertyListSubClass: TCFType {
6666
/// Create an instance of the superclass type [`CFPropertyList`] for this instance.
6767
///
6868
/// [`CFPropertyList`]: struct.CFPropertyList.html
6969
fn to_CFPropertyList(&self) -> CFPropertyList {
70-
unsafe { CFPropertyList::wrap_under_get_rule(self.as_concrete_TypeRef() as *const c_void) }
70+
unsafe { CFPropertyList::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr()) }
7171
}
7272
}
7373

74-
impl CFPropertyListSubClass<::data::__CFData> for ::data::CFData {}
75-
impl CFPropertyListSubClass<::string::__CFString> for ::string::CFString {}
76-
impl CFPropertyListSubClass<::array::__CFArray> for ::array::CFArray {}
77-
impl CFPropertyListSubClass<::dictionary::__CFDictionary> for ::dictionary::CFDictionary {}
78-
impl CFPropertyListSubClass<::date::__CFDate> for ::date::CFDate {}
79-
impl CFPropertyListSubClass<::number::__CFBoolean> for ::boolean::CFBoolean {}
80-
impl CFPropertyListSubClass<::number::__CFNumber> for ::number::CFNumber {}
74+
impl CFPropertyListSubClass for ::data::CFData {}
75+
impl CFPropertyListSubClass for ::string::CFString {}
76+
impl CFPropertyListSubClass for ::array::CFArray {}
77+
impl CFPropertyListSubClass for ::dictionary::CFDictionary {}
78+
impl CFPropertyListSubClass for ::date::CFDate {}
79+
impl CFPropertyListSubClass for ::boolean::CFBoolean {}
80+
impl CFPropertyListSubClass for ::number::CFNumber {}
8181

8282
/// A CFPropertyList struct. This is superclass to [`CFData`], [`CFString`], [`CFArray`],
8383
/// [`CFDictionary`], [`CFDate`], [`CFBoolean`], and [`CFNumber`].
@@ -151,10 +151,8 @@ impl CFPropertyList {
151151

152152
/// Returns true if this value is an instance of another type.
153153
#[inline]
154-
pub fn instance_of<OtherConcreteTypeRef, OtherCFType: TCFType<OtherConcreteTypeRef>>(
155-
&self,
156-
) -> bool {
157-
self.type_of() == <OtherCFType as TCFType<_>>::type_id()
154+
pub fn instance_of<OtherCFType: TCFType>(&self) -> bool {
155+
self.type_of() == <OtherCFType as TCFType>::type_id()
158156
}
159157
}
160158

@@ -190,14 +188,17 @@ impl CFPropertyList {
190188
/// // Cast it up to a property list.
191189
/// let propertylist: CFPropertyList = string.to_CFPropertyList();
192190
/// // Cast it down again.
193-
/// assert!(propertylist.downcast::<_, CFString>().unwrap().to_string() == "FooBar");
191+
/// assert!(propertylist.downcast::<CFString>().unwrap().to_string() == "FooBar");
194192
/// ```
195193
///
196194
/// [`CFPropertyList`]: struct.CFPropertyList.html
197195
/// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
198-
pub fn downcast<Raw, T: CFPropertyListSubClass<Raw>>(&self) -> Option<T> {
199-
if self.instance_of::<_, T>() {
200-
Some(unsafe { T::wrap_under_get_rule(self.0 as *const Raw) })
196+
pub fn downcast<T: CFPropertyListSubClass>(&self) -> Option<T> {
197+
if self.instance_of::<T>() {
198+
let subclass_ref = <T as TCFType>::ConcreteTypeRef::from_void_ptr(self.0);
199+
unsafe {
200+
Some(T::wrap_under_get_rule(subclass_ref))
201+
}
201202
} else {
202203
None
203204
}
@@ -242,14 +243,14 @@ pub mod test {
242243
#[test]
243244
fn downcast_string() {
244245
let propertylist = CFString::from_static_string("Bar").to_CFPropertyList();
245-
assert!(propertylist.downcast::<_, CFString>().unwrap().to_string() == "Bar");
246-
assert!(propertylist.downcast::<_, CFBoolean>().is_none());
246+
assert!(propertylist.downcast::<CFString>().unwrap().to_string() == "Bar");
247+
assert!(propertylist.downcast::<CFBoolean>().is_none());
247248
}
248249

249250
#[test]
250251
fn downcast_boolean() {
251252
let propertylist = CFBoolean::true_value().to_CFPropertyList();
252-
assert!(propertylist.downcast::<_, CFBoolean>().is_some());
253-
assert!(propertylist.downcast::<_, CFString>().is_none());
253+
assert!(propertylist.downcast::<CFBoolean>().is_some());
254+
assert!(propertylist.downcast::<CFString>().is_none());
254255
}
255256
}

core-foundation/src/set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl_CFTypeDescription!(CFSet);
3333

3434
impl CFSet {
3535
/// Creates a new set from a list of `CFType` instances.
36-
pub fn from_slice<R, T>(elems: &[T]) -> CFSet where T: TCFType<R> {
36+
pub fn from_slice<T>(elems: &[T]) -> CFSet where T: TCFType {
3737
unsafe {
3838
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
3939
let set_ref = CFSetCreate(kCFAllocatorDefault,

0 commit comments

Comments
 (0)