use base::{ AbstractCFType, AbstractCFTypeRef, CFAllocatorRef, CFIndex, CFRange, CFRelease, CFTypeRef, kCFAllocatorDefault, }; use libc::c_void; pub type CFArrayRetainCallBack = *u8; pub type CFArrayReleaseCallBack = *u8; pub type CFArrayCopyDescriptionCallBack = *u8; pub type CFArrayEqualCallBack = *u8; pub struct CFArrayCallBacks { version: CFIndex, retain: CFArrayRetainCallBack, release: CFArrayReleaseCallBack, copyDescription: CFArrayCopyDescriptionCallBack, equal: CFArrayEqualCallBack, } struct __CFArray { private: () } pub type CFArrayRef = *__CFArray; impl CFArrayRef : AbstractCFTypeRef { pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } } struct CFArray> { obj: CFArrayRef, drop { unsafe { CFRelease(cast::transmute(self.obj)) } } } pub impl> CFArray { static fn new(elems: &[ElemType]) -> CFArray { let array_ref : CFArrayRef; let elems_refs = do vec::map(elems) |e: &ElemType| { e.get_ref().as_type_ref() }; unsafe { array_ref = CFArrayCreate(kCFAllocatorDefault, cast::transmute(vec::raw::to_ptr(elems_refs)), elems.len() as CFIndex, ptr::to_unsafe_ptr(&kCFTypeArrayCallBacks)); } // return CFArray::wrap(array_ref) return CFArray { obj: array_ref }; } pub fn each(cb: fn&(ElemRefType) -> A) { for uint::range(0, self.len()) |i| { cb(self[i]); } } pub fn eachi(cb: fn&(uint, ElemRefType) -> A) { for uint::range(0, self.len()) |i| { cb(i, self[i]); } } pub pure fn len() -> uint { unsafe { return CFArrayGetCount(self.obj) as uint; } } } pub impl> CFArray : AbstractCFType { pure fn get_ref() -> CFArrayRef { self.obj } static fn wrap(obj: CFArrayRef) -> CFArray { CFArray { obj: obj } } static fn unwrap(wrapper: CFArray) -> CFArrayRef { wrapper.obj } } pub impl> CFArray : Index { pure fn index(idx: uint) -> ElemRefType { assert idx < self.len(); unsafe { let elem = CFArrayGetValueAtIndex(self.obj, idx as CFIndex); // Don't return a wrapped thing, since we don't know whether // it needs base::wrap() or base::wrap_borrowed() return cast::transmute(elem); } } } #[link_args="-framework CoreFoundation"] #[nolink] extern { /* * CFArray.h */ const kCFTypeArrayCallBacks: CFArrayCallBacks; fn CFArrayCreate(allocator: CFAllocatorRef, values: **c_void, numValues: CFIndex, callBacks: *CFArrayCallBacks) -> CFArrayRef; fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *c_void; fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex; } #[test] fn should_box_and_unbox() { use number::CFNumber; let arr = CFArray::new([ CFNumber::new(1 as i32), CFNumber::new(2 as i32), CFNumber::new(3 as i32), CFNumber::new(4 as i32), CFNumber::new(5 as i32)]); let mut sum = 0i32; // TODO: not always safe to re-wrap, unless we addref the element for arr.each |elem| { sum += elem.to_i32(); } assert sum == 15; }