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}