@@ -30,7 +30,7 @@ pub use url::CFUrl;
3030
3131/// An ID representing different [`CFType`] subclasses (and of course, [`CFType`]. itself). Can
3232/// be used for dynamic upcasting and downcasting of values.
33- #[ derive( Copy , Clone , PartialEq , Eq ) ]
33+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
3434pub struct CFTypeId ( libc:: c_ulong ) ;
3535
3636impl CFTypeId {
@@ -56,7 +56,12 @@ pub struct CFType(NonNull<()>);
5656impl CFType {
5757 /// Attempt to convert this type into a more specific child type. If the cast fails, `Err`
5858 /// contains the original [`CFType`].
59- pub fn downcast < T : CoreType > ( self ) -> Result < T , Self > {
59+ ///
60+ /// # Safety
61+ ///
62+ /// This method cannot check the validity of casting from `CFArray<T> -> CFType -> CFArray<U>`
63+ /// in general. It is an obligation of the caller to ensure the container type is preserved.
64+ pub unsafe fn downcast < T : CoreType > ( self ) -> Result < T , Self > {
6065 if CFTypeId :: of_val ( & self ) == CFTypeId :: of :: < T > ( ) {
6166 let this = ManuallyDrop :: new ( self ) ;
6267 // SAFETY: If the CFTypeId of self matches T, then it is guaranteed a valid pointer to T.
@@ -111,7 +116,8 @@ pub unsafe trait CoreType: Sized {
111116 /// The system type for this value. This is a pointer type in the `sys` module generally.
112117 type SysTy ;
113118
114- /// The [`CFTypeId`] that this type represents.
119+ /// The [`CFTypeId`] that this type represents. This is insufficient to ensure equality - for
120+ /// example, [`CFArray<A>`]` == `[`CFArray<B>`]
115121 fn type_id ( ) -> CFTypeId ;
116122
117123 /// # Safety
@@ -137,3 +143,28 @@ pub unsafe trait CoreType: Sized {
137143 /// Upcast this value into a [`CFType`] for usage in generic contexts.
138144 fn into_ty ( self ) -> CFType ;
139145}
146+
147+ #[ cfg( test) ]
148+ mod tests {
149+ use super :: * ;
150+
151+ #[ test]
152+ fn test_type_id ( ) {
153+ let arr = CFArray :: < CFType > :: empty ( ) ;
154+ assert_eq ! ( CFTypeId :: of:: <CFArray <CFType >>( ) , CFTypeId :: of_val( & arr) ) ;
155+ assert_eq ! (
156+ CFTypeId :: of:: <CFArray <CFString >>( ) ,
157+ CFTypeId :: of:: <CFArray <CFUrl >>( )
158+ ) ;
159+ assert_ne ! ( CFTypeId :: of:: <CFString >( ) , CFTypeId :: of:: <CFUrl >( ) ) ;
160+ }
161+
162+ #[ test]
163+ fn test_upcast ( ) {
164+ let arr = CFArray :: < CFType > :: empty ( ) ;
165+ let ty = arr. into_ty ( ) ;
166+
167+ assert_eq ! ( CFTypeId :: of_val( & ty) , CFTypeId :: of:: <CFArray <CFType >>( ) ) ;
168+ drop ( ty) ;
169+ }
170+ }
0 commit comments