Skip to main content

cidre/cf/
runtime.rs

1use std::{ffi::c_void, ptr::NonNull};
2
3use super::TypeId;
4
5use crate::{arc, cf};
6
7// #[derive(Debug)]
8#[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}