diff --git a/array.rs b/array.rs index 099b0de..35652db 100644 --- a/array.rs +++ b/array.rs @@ -3,6 +3,7 @@ use base::{ CFAllocatorRef, CFIndex, CFRange, + CFTypeID, CFTypeRef, CFWrapper, kCFAllocatorDefault, @@ -27,6 +28,7 @@ pub type CFArrayRef = *__CFArray; pub impl CFArrayRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFArrayGetTypeID() } } pub type CFArray = CFWrapper; @@ -95,9 +97,17 @@ extern { fn CFArrayCreate(allocator: CFAllocatorRef, values: **c_void, numValues: CFIndex, callBacks: *CFArrayCallBacks) -> CFArrayRef; - - fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *c_void; + // CFArrayCreateCopy + // CFArrayBSearchValues + // CFArrayContainsValue fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex; + // CFArrayGetCountOfValue + // CFArrayGetFirstIndexOfValue + // CFArrayGetLastIndexOfValue + // CFArrayGetValues + fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *c_void; + // CFArrayApplyFunction + fn CFArrayGetTypeID() -> CFTypeID; } #[test] diff --git a/base.rs b/base.rs index 382e482..050487d 100644 --- a/base.rs +++ b/base.rs @@ -5,6 +5,7 @@ use libc::c_long; // borrow semantics. trait AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef; + static pure fn type_id() -> CFTypeID; } pub type Boolean = u8; @@ -35,6 +36,13 @@ pub type CFTypeRef = *__CFType; pub impl CFTypeRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self } + // this can't be used, because CFType is the supertype and has no type id. + static pure fn type_id() -> CFTypeID { fail; } +} + +pub pure fn downcast(r: CFTypeRef) -> T unsafe { + assert CFGetTypeID(r) == type_id::(); + cast::transmute(r) } struct CFWrapper { @@ -89,6 +97,7 @@ pub impl } static fn from_CFType(wrapper: CFType) -> CFWrapper unsafe { + assert wrapper.type_id() == type_id::(); cast::transmute(move wrapper) } diff --git a/boolean.rs b/boolean.rs index ca20c7c..11f053f 100644 --- a/boolean.rs +++ b/boolean.rs @@ -1,14 +1,18 @@ use base::{ AbstractCFTypeRef, CFTypeRef, + CFTypeID, CFWrapper, }; +pub type Boolean = u32; + struct __CFBoolean { private: () } pub type CFBooleanRef = *__CFBoolean; pub impl CFBooleanRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFBooleanGetTypeID() } } pub type CFBoolean = CFWrapper; @@ -28,5 +32,8 @@ pub impl CFBoolean { extern { const kCFBooleanTrue: CFBooleanRef; const kCFBooleanFalse: CFBooleanRef; + + fn CFBooleanGetValue(boolean: CFBooleanRef) -> Boolean; + fn CFBooleanGetTypeID() -> CFTypeID; } diff --git a/data.rs b/data.rs index 2a07cd5..f647b07 100644 --- a/data.rs +++ b/data.rs @@ -3,8 +3,8 @@ use base::{ CFAllocatorRef, CFIndex, CFRange, - CFType, CFTypeRef, + CFTypeID, CFWrapper, kCFAllocatorDefault, }; @@ -16,6 +16,7 @@ pub type CFDataRef = *__CFData; impl CFDataRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFDataGetTypeID() } } type CFData = CFWrapper; @@ -66,4 +67,6 @@ extern { fn CFDataGetBytePtr(theData: CFDataRef) -> *u8; fn CFDataGetBytes(theData: CFDataRef, range: CFRange, buffer: *u8); fn CFDataGetLength(theData: CFDataRef) -> CFIndex; + + fn CFDataGetTypeID() -> CFTypeID; } diff --git a/dictionary.rs b/dictionary.rs index ca8de07..937a533 100644 --- a/dictionary.rs +++ b/dictionary.rs @@ -43,6 +43,7 @@ pub type CFDictionaryRef = *__CFDictionary; impl CFDictionaryRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFDictionaryGetTypeID() } } pub type CFDictionary = CFWrapper; diff --git a/number.rs b/number.rs index 657fb2b..1b7d702 100644 --- a/number.rs +++ b/number.rs @@ -36,6 +36,7 @@ pub type CFNumberRef = *__CFNumber; pub impl CFNumberRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFNumberGetTypeID() } } pub impl CFNumberRef { @@ -159,3 +160,13 @@ extern { //fn CFNumberCompare fn CFNumberGetTypeID() -> CFTypeID; } + +fn should_fail_on_bad_downcast() { + #[test]; + #[should_fail]; + + use boolean::CFBooleanRef; + + let one = CFWrapper::to_CFType(CFNumber::new(1_i32)); + let casted = base::downcast::(*one.borrow_ref()); +} \ No newline at end of file diff --git a/set.rs b/set.rs index 176b012..6f5a80c 100644 --- a/set.rs +++ b/set.rs @@ -30,6 +30,7 @@ pub type CFSetRef = *__CFSet; impl CFSetRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFSetGetTypeID() } } pub type CFSet = CFWrapper; diff --git a/string.rs b/string.rs index 0459351..952ad78 100644 --- a/string.rs +++ b/string.rs @@ -199,6 +199,7 @@ pub type CFStringRef = *__CFString; pub impl CFStringRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFStringGetTypeID() } } pub type CFString = CFWrapper; diff --git a/test.rs b/test.rs index b535b6b..be0c2c0 100644 --- a/test.rs +++ b/test.rs @@ -22,4 +22,3 @@ fn main() { ]); d.show(); } - diff --git a/url.rs b/url.rs index 7c75c60..44e62f2 100644 --- a/url.rs +++ b/url.rs @@ -20,6 +20,7 @@ pub type CFURLRef = *__CFURL; impl CFURLRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + static pure fn type_id() -> CFTypeID unsafe { CFURLGetTypeID() } } pub type CFURL = CFWrapper;