Auto merge of #148 - jrmuizel:bounds-check, r=jdm

Lift getting the length of the array out.

This changes get() to return an Option<> and adds a get_unchecked() that doesn't do a bounds check. This means our bounds check can be inlined into the caller instead of us having to CFArrayGetCount twice for each element.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/core-foundation-rs/148)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo
2018-01-25 13:22:59 -06:00
committed by GitHub
+18 -8
View File
@@ -70,16 +70,17 @@ impl<T> Drop for CFArray<T> {
pub struct CFArrayIterator<'a, T: 'a> {
array: &'a CFArray<T>,
index: CFIndex,
len: CFIndex,
}
impl<'a, T: FromVoid> Iterator for CFArrayIterator<'a, T> {
type Item = ItemRef<'a, T>;
fn next(&mut self) -> Option<ItemRef<'a, T>> {
if self.index >= self.array.len() {
if self.index >= self.len {
None
} else {
let value = self.array.get(self.index);
let value = unsafe { self.array.get_unchecked(self.index) };
self.index += 1;
Some(value)
}
@@ -131,7 +132,8 @@ impl<T> CFArray<T> {
pub fn iter<'a>(&'a self) -> CFArrayIterator<'a, T> {
CFArrayIterator {
array: self,
index: 0
index: 0,
len: self.len(),
}
}
@@ -143,9 +145,17 @@ impl<T> CFArray<T> {
}
#[inline]
pub fn get<'a>(&'a self, index: CFIndex) -> ItemRef<'a, T> where T: FromVoid {
assert!(index < self.len());
unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) }
pub unsafe fn get_unchecked<'a>(&'a self, index: CFIndex) -> ItemRef<'a, T> where T: FromVoid {
T::from_void(CFArrayGetValueAtIndex(self.0, index))
}
#[inline]
pub fn get<'a>(&'a self, index: CFIndex) -> Option<ItemRef<'a, T>> where T: FromVoid {
if index < self.len() {
Some(unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) } )
} else {
None
}
}
pub fn get_values(&self, range: CFRange) -> Vec<*const c_void> {
@@ -216,11 +226,11 @@ mod tests {
{
let arr: CFArray<CFString> = CFArray::from_CFTypes(&[string]);
{
let p = arr.get(0);
let p = arr.get(0).unwrap();
assert_eq!(p.retain_count(), 1);
}
{
x = arr.get(0).clone();
x = arr.get(0).unwrap().clone();
assert_eq!(x.retain_count(), 2);
assert_eq!(x.to_string(), "bar");
}