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 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.
Add the ability to borrow values from the array.
This is a replacement for #143. It allows iteration while avoiding the reference count churn of the previous approach. It uses a TCFTypeBorrow (could probably use a better name) to hold a sort of reference to the array data. I'm interested in people's thoughts and opinions on this approach.
<!-- 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/147)
<!-- Reviewable:end -->
Reference type as associated value instead of generic
Each `CFFoo` has exactly one `CFFooRef` and which one is defined by `CFFoo`, not by its user. Thus the type of reference can be an associated type instead of a generic.
As you can see this greatly simplifies things such as calling `instance_of` and `from_CFType_pairs` as well as using `CFPropertyListSubClass`. It basically removes one generic parameter from any method dealing with `TCFType`s in some way.
This is a breaking change, so it would probably mean a `0.5.0` release if accepted. I don't know what your stance on breaking changes or version bumps is, so I don't know if you want this or not. But it would simplify the API, both here, but first and foremost in higher level crates using this.
<!-- 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/132)
<!-- Reviewable:end -->
Various fixes and rearrangements
A couple of things that I found easy to do that would improve the readability and usability of the crate in various ways. Some might be more subjectively better rather than objectively better. I clogged some unrelated changes into the same PR since the merge process takes ages with Travis being this slow. Anyway, they all fit under the "cleanup" category :) Tell me if you want them split into multiple PRs.
* Export the sys part of the error module. All other modules do this. I guess it was missed?
* Fix so the macros are usable from other crates without having to depend on `core-foundation-sys` or import `CFRelease` into the scope where they are used.
* The tests in `lib.rs` were only testing the dictionary implementations, so I moved them to `dictionary.rs`
* I found it a bit undiscoverable that `CFRunLoopSource` define a method inside of `filedescriptor.rs`. At the same time it's not ideal to call the ffi-methods of the filedescriptor from runloop.rs. This rearrangement solves both of those problems by exposing `CFFileDescriptor::to_run_loop_source` that can be used from `runloop.rs`.
<!-- 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/145)
<!-- Reviewable:end -->
Add consuming cheap cast
There are a lot of places where we increment and decrement the retain count when we would not have to. For example, a very common use-case with PropertyLists is to just directly cast them to their correct sub type and then throw the PropertyList away (because there is nothing you can do with the PropertyList instance directly.)
The reason we do this, I guess, is mostly because all `Drop` implementations force a retain count decrement. So we have to keep incrementing it to keep it correct. But if we add a flag to types that can be used to disable the decrement, then we can also get rid of the increment when we virtually just want to cast a pointer between two types.
This PR implements this by adding a boolean flag to all CF structs that is used by the `Drop` impl to determine if it should `CFRelease` the instance or not. Then this flag is modified in appropriate places where we cast to other types and consume ourselves.
I added some benchmarks locally. I did not want to commit them since benchmarking only works on nighty, and I did not feel like adding a feature flag for it etc. Anyhow, the following benchmarks:
```rust
#[bench]
fn bench_before(b: &mut Bencher) {
let string = CFString::from_static_string("Bar");
b.iter(|| unsafe {
string.clone()
.to_CFPropertyList()
.downcast::<_, CFString>()
.unwrap()
.disable_release();
})
}
#[bench]
fn bench_after(b: &mut Bencher) {
let string = CFString::from_static_string("Bar");
b.iter(|| unsafe {
string.clone()
.into_CFPropertyList()
.downcast_into::<_, CFString>()
.unwrap()
.disable_release();
})
}
```
Given the following results:
```
test propertylist::test::bench_after ... bench: 16 ns/iter (+/- 3)
test propertylist::test::bench_before ... bench: 73 ns/iter (+/- 14)
```
The final call to `disable_release()` in the benchmarks are to prevent the type coming out of the `unwrap()` from calling `CFRelease` on drop, and thus avoid measuring that. I want to try to measure only `{to,into}_CFPropertyList`, `downcast` and `downcast_into`. The `clone` is needed because the `into` version requires it and it would then not be fair to not have it on both.
I would say that speeding it up by a factor of ~4 can be well worth it? (Well, that 4 is of course no good measurement of anything, microbenchmarks etc. etc.. The benchmark mostly shows that a lot can be gained from avoiding some retain counting.)
<!-- 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/142)
<!-- Reviewable:end -->
Add CFMutableDictionary type.
Added CFMutableDictionary that presents the mutable dictionary
functions of CF. Tries to present a similar interface as CFDictionary.
Fixes issue #93.
<!-- 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/135)
<!-- Reviewable:end -->
Fix timing sensitive test
This problem was found when I tried to debug #132
But since that PR grew so large, and this fix was very unrelated to the work in that PR I split it out to a separate one.
<!-- 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/141)
<!-- Reviewable:end -->
Fix bug in CFArray::to_untyped that made the retain count wrong
The following code segfaults on the `0.4.5` release:
```rust
CFArray::<CFBoolean>::from_CFTypes(&[]).to_untyped().to_untyped().to_untyped()
```
Because `to_untyped` don't increment the retain count, but when the typed array it's created from goes out of scope that one will decrement it.
And since we need to wrap under the get rule (call `CFRetain`) anyway I did not see any reason to have it as a consuming `to_` method. It's more flexible as a borrowing `as_` method.
Since you probably don't want to cause API breakage I kept the old version but fixed the bug and added a deprecation notice on it.
<!-- 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/139)
<!-- Reviewable:end -->
Implement From<_> for CFNumber
All the `from_` methods on `CFNumber` can be expressed with implementing the `From` trait and thus enable it to be used a bit more ergonomic in some cases. And feels more idiomatic IMO.
<!-- 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/137)
<!-- Reviewable:end -->