use std::fmt;
pub use core_foundation_sys::base::*;
use string::CFString;
pub trait CFIndexConvertible {
fn to_CFIndex(self) -> CFIndex;
}
impl CFIndexConvertible for usize {
#[inline]
fn to_CFIndex(self) -> CFIndex {
let max_CFIndex = CFIndex::max_value();
if self > (max_CFIndex as usize) {
panic!("value out of range")
}
self as CFIndex
}
}
pub struct CFType(CFTypeRef);
impl fmt::Debug for CFType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let desc = unsafe {
CFString::wrap_under_create_rule(CFCopyDescription(self.0))
};
desc.fmt(f)
}
}
impl Clone for CFType {
#[inline]
fn clone(&self) -> CFType {
unsafe {
TCFType::wrap_under_get_rule(self.0)
}
}
}
impl PartialEq for CFType {
#[inline]
fn eq(&self, other: &CFType) -> bool {
unsafe {
CFEqual(self.as_CFTypeRef(), other.as_CFTypeRef()) != 0
}
}
}
impl Drop for CFType {
fn drop(&mut self) {
unsafe {
CFRelease(self.0)
}
}
}
pub struct CFAllocator(CFAllocatorRef);
impl Drop for CFAllocator {
fn drop(&mut self) {
unsafe {
CFRelease(self.as_CFTypeRef())
}
}
}
impl_TCFType!(CFAllocator, CFAllocatorRef, CFAllocatorGetTypeID);
impl CFAllocator {
#[inline]
pub fn new(mut context: CFAllocatorContext) -> CFAllocator {
unsafe {
let allocator_ref = CFAllocatorCreate(kCFAllocatorDefault, &mut context);
TCFType::wrap_under_create_rule(allocator_ref)
}
}
}
pub trait TCFType<ConcreteTypeRef> {
fn as_concrete_TypeRef(&self) -> ConcreteTypeRef;
unsafe fn wrap_under_create_rule(obj: ConcreteTypeRef) -> Self;
fn type_id() -> CFTypeID;
#[inline]
fn as_CFType(&self) -> CFType {
unsafe {
TCFType::wrap_under_get_rule(self.as_CFTypeRef())
}
}
fn as_CFTypeRef(&self) -> CFTypeRef;
unsafe fn wrap_under_get_rule(reference: ConcreteTypeRef) -> Self;
#[inline]
fn retain_count(&self) -> CFIndex {
unsafe {
CFGetRetainCount(self.as_CFTypeRef())
}
}
#[inline]
fn type_of(&self) -> CFTypeID {
unsafe {
CFGetTypeID(self.as_CFTypeRef())
}
}
fn show(&self) {
unsafe {
CFShow(self.as_CFTypeRef())
}
}
#[inline]
fn instance_of<OtherConcreteTypeRef,OtherCFType:TCFType<OtherConcreteTypeRef>>(&self) -> bool {
self.type_of() == <OtherCFType as TCFType<_>>::type_id()
}
}
impl TCFType<CFTypeRef> for CFType {
#[inline]
fn as_concrete_TypeRef(&self) -> CFTypeRef {
self.0
}
#[inline]
unsafe fn wrap_under_get_rule(reference: CFTypeRef) -> CFType {
let reference: CFTypeRef = CFRetain(reference);
TCFType::wrap_under_create_rule(reference)
}
#[inline]
fn as_CFTypeRef(&self) -> CFTypeRef {
self.as_concrete_TypeRef()
}
#[inline]
unsafe fn wrap_under_create_rule(obj: CFTypeRef) -> CFType {
CFType(obj)
}
#[inline]
fn type_id() -> CFTypeID {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
use boolean::CFBoolean;
#[test]
fn cftype_instance_of() {
let string = CFString::from_static_string("foo");
let cftype = string.as_CFType();
assert!(cftype.instance_of::<_, CFString>());
assert!(!cftype.instance_of::<_, CFBoolean>());
}
}