objc2_core_foundation/
type_traits.rs

1use core::ptr::NonNull;
2
3use crate::{CFRetained, CFType, CFTypeID};
4
5/// A CoreFoundation-like type.
6///
7/// This trait is implemented for all CoreFoundation-like types (i.e. both
8/// types in this crate like `CFString`, but also types from other frameworks
9/// like `CGColor` from CoreGraphics).
10///
11/// This trait allows the type to be used in [`CFRetained`].
12///
13/// You should not need to implement this yourself.
14///
15///
16/// # Safety
17///
18/// - The type must be a CoreFoundation-like type.
19/// - The type must be safe to retain/release using `CFRetain` and
20///   `CFRelease`.
21pub unsafe trait Type {
22    /// Increment the reference count of the receiver.
23    ///
24    /// This extends the duration in which the receiver is alive by detaching
25    /// it from the lifetime information carried by the reference.
26    ///
27    /// This is similar to using [`Clone` on `CFRetained<Self>`][clone-id],
28    /// with the addition that it can be used on a plain reference.
29    ///
30    /// [clone-id]: crate::CFRetained#impl-Clone-for-CFRetained<T>
31    #[inline]
32    #[doc(alias = "CFRetain")]
33    fn retain(&self) -> CFRetained<Self>
34    where
35        Self: Sized,
36    {
37        let ptr = NonNull::from(self);
38
39        // SAFETY: The pointer is valid, since it came from a Rust reference.
40        unsafe { CFRetained::retain(ptr) }
41    }
42
43    /// Helper for easier transition from the `core-foundation` crate.
44    #[deprecated = "this is redundant"]
45    #[inline]
46    #[allow(non_snake_case)]
47    fn as_concrete_TypeRef(&self) -> &Self {
48        self
49    }
50
51    /// Helper for easier transition from the `core-foundation` crate.
52    ///
53    /// # Safety
54    ///
55    /// Same as [`CFRetained::retain`].
56    #[deprecated = "use CFRetained::retain"]
57    #[inline]
58    unsafe fn wrap_under_get_rule(ptr: *const Self) -> CFRetained<Self>
59    where
60        Self: Sized,
61    {
62        let ptr = NonNull::new(ptr.cast_mut()).expect("attempted to create a NULL object");
63        // SAFETY: Upheld by caller.
64        unsafe { CFRetained::retain(ptr) }
65    }
66
67    /// Helper for easier transition from the `core-foundation` crate.
68    #[deprecated = "this is redundant (CF types deref to CFType)"]
69    #[inline]
70    #[allow(non_snake_case)]
71    fn as_CFTypeRef(&self) -> &CFType
72    where
73        Self: AsRef<CFType>,
74    {
75        self.as_ref()
76    }
77
78    /// Helper for easier transition from the `core-foundation` crate.
79    ///
80    /// # Safety
81    ///
82    /// Same as [`CFRetained::from_raw`].
83    #[deprecated = "use CFRetained::from_raw"]
84    #[inline]
85    unsafe fn wrap_under_create_rule(ptr: *const Self) -> CFRetained<Self>
86    where
87        Self: Sized,
88    {
89        let ptr = NonNull::new(ptr.cast_mut()).expect("attempted to create a NULL object");
90        // SAFETY: Upheld by caller.
91        unsafe { CFRetained::from_raw(ptr) }
92    }
93}
94
95/// A concrete CoreFoundation type.
96///
97/// This trait is implemented for CoreFoundation types which have a
98/// `CFTypeID`, which should be most types except for mutable variants, types
99/// with generics, as well as the root `CFType`.
100///
101///
102/// # Mutable types
103///
104/// Some types have immutable and mutable variants, the prime example being
105/// `CFString` and `CFMutableString`. Internally, these are very complex class
106/// clusters, but in the simplest case they're sometimes the same type, the
107/// only difference being that the mutable variant has a boolean flag set.
108/// This means that they also share the same type ID, and thus we cannot
109/// (stably) differentiate between them at runtime.
110///
111/// Therefore, this trait is only implemented for the immutable variant, to
112/// prevent it from accidentally being misused (it is unclear whether it would
113/// be unsound or not). If you're looking to convert to a mutable type, you'll
114/// have to either construct a new one with APIs like
115/// `CFStringCreateMutableCopy`, or use an unchecked cast.
116///
117///
118/// # Generic types
119///
120/// Only the "base" type / the type without generics implements this.
121///
122/// So for example, `CFArray` implements this trait, but `CFArray<CFString>`
123/// does not (as we cannot query the type of the inner element without
124/// actually inspecting the element, and since `CFArray`s aren't required to
125/// hold CF types).
126///
127///
128/// # Safety
129///
130/// - The type must not be mutable.
131/// - The type must not be generic (e.g. this can only be implemented for the
132///   base `CFArray`, not for all `CFArray<T>`).
133/// - The [`type_id`][Self::type_id] must be implemented correctly, and must
134///   uniquely identify the type.
135pub unsafe trait ConcreteType: Type {
136    /// Get the unique `CFTypeID` identifier for the type.
137    ///
138    /// For example, this corresponds to `CFStringGetTypeID` for `CFString`
139    /// and `CGColorGetTypeID` for `CGColor`.
140    #[doc(alias = "GetTypeID")]
141    fn type_id() -> CFTypeID;
142}