Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CFPropertyList and methods for casting to subclasses #131

Merged
merged 4 commits into from Nov 24, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Improve documentation with links

  • Loading branch information
faern committed Nov 24, 2017
commit 343b0c9a9a431277766e9684d0f75de7cd50d74a
@@ -60,9 +60,13 @@ pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -
}


/// Trait for all subclasses of CFPropertyList.
/// Trait for all subclasses of [`CFPropertyList`].
///
/// [`CFPropertyList`]: struct.CFPropertyList.html
pub trait CFPropertyListSubClass<Raw>: TCFType<*const Raw> {

This comment has been minimized.

@jdm

jdm Nov 24, 2017

Member

We should be able to do pub trait CFPropertyListSubClass: TCFType<*const Self> { and avoid some redundancy in the implementations.

This comment has been minimized.

@faern

faern Nov 24, 2017

Author Contributor

Getting rid of the generic would be awesome. But I don't understand exactly how that would work. Self here is CFString or similar.

This comment has been minimized.

@faern

faern Nov 24, 2017

Author Contributor

Separate from this I'm working on trying to make the ConcreteTypeRef in TCFType a associated type instead of a generic. When/if that works out this can be greatly simplified.

This comment has been minimized.

@jdm

jdm Nov 24, 2017

Member

impl CFPropertyListSubClass<::data::__CFData> for ::data::CFData duplicates the type in two places. Using the snippet I provided, the resulting impl of impl CFPropertyListSubClass for ::data::CFData should work just fine: https://play.rust-lang.org/?gist=b89fc9fe403069fd843f6054897f21db&version=stable

This comment has been minimized.

@faern

faern Nov 24, 2017

Author Contributor

Yes, but impl U<*const u32> for u32 {} does not hold for us.

Our CFString does not impl TCFType<*const CFString>, it implements it for TCFType<*const __CFString>.

This comment has been minimized.

@faern

faern Nov 24, 2017

Author Contributor

The existance of both CFStringRef and __CFString makes it complicated in more than one situation for me. I can't cast between pointers in the downcast method because the compiler does not know that CFStringRef is a raw pointer. It is, and all *Ref are *const _, but the compiler does not know. Which forces me to reference the underlying *const __CF<Foo> types in order to show the compiler the casts are fine. Maybe it's possible to work around it in some way, but I have not found one yet.

This comment has been minimized.

@jdm

jdm Nov 24, 2017

Member

Oh, whoops. I didn't notice the underscores in the type name.

This comment has been minimized.

@faern

faern Nov 24, 2017

Author Contributor

Easy thing to do. Lots of types with very similar names here :)

/// Create an instance of the superclass type `CFPropertyList` for this instance.
/// Create an instance of the superclass type [`CFPropertyList`] for this instance.
///
/// [`CFPropertyList`]: struct.CFPropertyList.html
fn to_CFPropertyList(&self) -> CFPropertyList {
unsafe { CFPropertyList::wrap_under_get_rule(self.as_concrete_TypeRef() as *const c_void) }
}
@@ -76,12 +80,22 @@ impl CFPropertyListSubClass<::date::__CFDate> for ::date::CFDate {}
impl CFPropertyListSubClass<::number::__CFBoolean> for ::boolean::CFBoolean {}
impl CFPropertyListSubClass<::number::__CFNumber> for ::number::CFNumber {}

/// A CFPropertyList struct. This is superclass to CFData, CFString, CFArray, CFDictionary,
/// CFDate, CFBoolean, and CFNumber.
/// A CFPropertyList struct. This is superclass to [`CFData`], [`CFString`], [`CFArray`],
/// [`CFDictionary`], [`CFDate`], [`CFBoolean`], and [`CFNumber`].
///
/// This superclass type does not have its own CFTypeID, instead each instance has the CFTypeID of
/// the subclass it is an instance of. Thus, this type cannot implement the `TCFType` trait, since
/// it cannot implement the static `TCFType::type_id()` method.
/// This superclass type does not have its own `CFTypeID`, instead each instance has the `CFTypeID`
/// of the subclass it is an instance of. Thus, this type cannot implement the [`TCFType`] trait,
/// since it cannot implement the static [`TCFType::type_id()`] method.
///
/// [`CFData`]: ../data/struct.CFData.html
/// [`CFString`]: ../string/struct.CFString.html
/// [`CFArray`]: ../array/struct.CFArray.html
/// [`CFDictionary`]: ../dictionary/struct.CFDictionary.html
/// [`CFDate`]: ../date/struct.CFDate.html
/// [`CFBoolean`]: ../boolean/struct.CFBoolean.html
/// [`CFNumber`]: ../number/struct.CFNumber.html
/// [`TCFType`]: ../base/trait.TCFType.html
/// [`TCFType::type_id()`]: ../base/trait.TCFType.html#method.type_of
pub struct CFPropertyList(CFPropertyListRef);

impl Drop for CFPropertyList {
@@ -162,9 +176,9 @@ impl PartialEq for CFPropertyList {
impl Eq for CFPropertyList {}

impl CFPropertyList {
/// Try to downcast the CFPropertyList to a subclass. Checking if the instance is the correct
/// Try to downcast the [`CFPropertyList`] to a subclass. Checking if the instance is the correct
/// subclass happens at runtime and an error is returned if it is not the correct type.
/// Works similar to `Box::downcast`.
/// Works similar to [`Box::downcast`].
///
/// # Examples
///
@@ -179,6 +193,9 @@ impl CFPropertyList {
/// // Cast it down again.
/// assert!(propertylist.downcast::<_, CFString>().unwrap().to_string() == "FooBar");
/// ```
///
/// [`CFPropertyList`]: struct.CFPropertyList.html
/// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
pub fn downcast<Raw, T: CFPropertyListSubClass<Raw>>(&self) -> Result<T, CFPropertyListCastError> {
if self.instance_of::<_, T>() {
Ok(unsafe { T::wrap_under_get_rule(self.0 as *const Raw) })
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.