1use std::{ffi::c_void, ptr::NonNull};
2
3use super::TypeId;
4
5use crate::{arc, cf};
6
7#[repr(transparent)]
9pub struct Type(NonNull<c_void>);
10
11impl Type {
12 #[inline]
13 pub unsafe fn retain<T: arc::Release>(cf: &Type) -> arc::R<T> {
14 unsafe { std::mem::transmute(CFRetain(cf)) }
15 }
16
17 #[inline]
18 pub unsafe fn release(cf: &mut Type) {
19 unsafe { CFRelease(cf) }
20 }
21
22 #[inline]
23 pub fn get_type_id(&self) -> TypeId {
24 unsafe { CFGetTypeID(self) }
25 }
26
27 #[inline]
28 pub unsafe fn as_type_ptr(&self) -> *const c_void {
29 self as *const Type as _
30 }
31
32 #[inline]
33 pub fn as_type_ref(&self) -> &Type {
34 self
35 }
36
37 #[cfg(not(target_os = "watchos"))]
38 #[inline]
39 pub fn is_tagged_ptr(&self) -> bool {
40 ((self as *const Self as usize) >> 63) == 1
41 }
42}
43
44impl arc::Retain for Type {
45 #[inline]
46 fn retained<'a>(&self) -> arc::R<Self> {
47 unsafe { Type::retain(self) }
48 }
49}
50
51impl arc::Release for Type {
52 #[inline]
53 unsafe fn release(&mut self) {
54 unsafe { Type::release(self) }
55 }
56}
57
58#[macro_export]
59macro_rules! define_cf_type {
60 (
61 $(#[$outer:meta])*
62 $NewType:ident($BaseType:path)
63 ) => {
64 $(#[$outer])*
65 #[derive(Debug)]
66 #[repr(transparent)]
67 pub struct $NewType($BaseType);
68
69 impl std::ops::Deref for $NewType {
70 type Target = $BaseType;
71
72 #[inline]
73 fn deref(&self) -> &Self::Target {
74 &self.0
75 }
76 }
77
78 impl std::ops::DerefMut for $NewType {
79 #[inline]
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 &mut self.0
82 }
83 }
84
85 impl $crate::arc::Release for $NewType {
86 #[inline]
87 unsafe fn release(&mut self) {
88 unsafe { self.0.release() }
89 }
90 }
91
92 impl $crate::arc::Retain for $NewType {
93 #[inline]
94 fn retained(&self) -> crate::arc::R<Self> {
95 $NewType::retained(self)
96 }
97 }
98
99 impl $NewType {
100 #[inline]
101 pub fn retained(&self) -> crate::arc::R<Self> {
102 unsafe { crate::cf::Type::retain(self) }
103 }
104 }
105
106 impl AsRef<$crate::cf::Type> for $NewType {
107 fn as_ref(&self) -> &$crate::cf::Type {
108 self
109 }
110 }
111 };
112}
113
114impl Type {
115 pub fn try_as_number(&self) -> Option<&cf::Number> {
116 if self.get_type_id() == cf::Number::type_id() {
117 Some(unsafe { std::mem::transmute(self) })
118 } else {
119 None
120 }
121 }
122
123 pub fn try_as_string(&self) -> Option<&cf::String> {
124 if self.get_type_id() == cf::String::type_id() {
125 Some(unsafe { std::mem::transmute(self) })
126 } else {
127 None
128 }
129 }
130}
131
132unsafe extern "C-unwind" {
133 fn CFRetain(cf: &Type) -> arc::R<Type>;
134 fn CFRelease(cf: &mut Type);
135 fn CFGetTypeID(cf: &Type) -> TypeId;
136}