core-foundation-rs
core-foundation-rs copied to clipboard
Encode retaining and releasing in types
This is an idea I'm thinking about these days, we should be able to not retain things when using the get rule, instead we should be able to rely on lifetimes.
use std::ops::{Deref, Drop};
pub trait Release {
unsafe fn release(&self);
}
pub struct Retained<T>(T) where T: Release;
impl<T: Release> Drop for Retained<T> {
fn drop(&mut self) {
unsafe {
self.0.release();
}
}
}
enum Opaque {}
pub struct CFURL(Opaque);
pub struct CFURLRef(*const CFURL);
impl Release for CFURLRef {
unsafe fn release(&self) {
...
}
}
impl Deref for CFURLRef {
type Target = CFURL;
fn deref(&self) -> &CFURL {
unsafe { &*self.0 }
}
}
With additional traits for casting to supertype CFTypeRef, we should be able to provide functions going from &CFString to Retained<CFStringRef>.
So I've realised we can encode things in a way simpler fashion:
use std::ops::{Deref, Drop};
pub trait Release {
unsafe fn release(&self);
}
pub struct Rc<T: Release>(*mut T);
impl<T: Release> Deref for Rc<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.0 }
}
}
impl<T: Release> Drop for Rc<T> {
fn drop(&mut self) {
unsafe {
(&mut *self.0).release();
}
}
}
enum Opaque {}
pub struct CFURL(Opaque);
impl Release for CFURL {
unsafe fn release(&self) {
...
}
}
Should I go ahead with this? I don't like the current situation, it's kinda like rust-mozjs but worse, because many things here are marked as safe even though they are just passed raw pointers.
Cc @metajack.
Cc @sfackler who wrote rust-security-framework and @dtwood who wrote core-midi-rs.
I recently overhauled rust-openssl to do this kind of thing, though with separate Foo and FooRef<'a> types rather than a type parameter: e.g. http://sfackler.github.io/rust-openssl/doc/v0.8.2/openssl/asn1/index.html
There are some other breaking changes I'd like to make to core-foundation-rs, so give me a heads up if you're preparing for a breaking release.
@sfackler I think it would be easier to have a type representing the refcounted things from CF, rather than 2 separate types for each. That would allow us to have a Unique<T: Release> wrapper of some sort, for CFMutableArray and friends.
Yeah, that sounds like a reasonable approach.
@sfackler I also have some neat ideas in mind, like CFString<'a> which would allow us to transparently make a CFString<'a> from a &'a str; will start doing that this week.