core_graphics/
data_provider.rs1use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType};
11use core_foundation::data::{CFData, CFDataRef};
12
13use libc::{off_t, size_t};
14use std::mem;
15use std::os::raw::c_void;
16use std::ptr;
17use std::sync::Arc;
18
19use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
20
21pub type CGDataProviderGetBytesCallback =
22 Option<unsafe extern "C" fn(*mut c_void, *mut c_void, size_t) -> size_t>;
23pub type CGDataProviderReleaseInfoCallback = Option<unsafe extern "C" fn(*mut c_void)>;
24pub type CGDataProviderRewindCallback = Option<unsafe extern "C" fn(*mut c_void)>;
25pub type CGDataProviderSkipBytesCallback = Option<unsafe extern "C" fn(*mut c_void, size_t)>;
26pub type CGDataProviderSkipForwardCallback =
27 Option<unsafe extern "C" fn(*mut c_void, off_t) -> off_t>;
28
29pub type CGDataProviderGetBytePointerCallback =
30 Option<unsafe extern "C" fn(*mut c_void) -> *mut c_void>;
31pub type CGDataProviderGetBytesAtOffsetCallback =
32 Option<unsafe extern "C" fn(*mut c_void, *mut c_void, size_t, size_t)>;
33pub type CGDataProviderReleaseBytePointerCallback =
34 Option<unsafe extern "C" fn(*mut c_void, *const c_void)>;
35pub type CGDataProviderReleaseDataCallback =
36 Option<unsafe extern "C" fn(*mut c_void, *const c_void, size_t)>;
37pub type CGDataProviderGetBytesAtPositionCallback =
38 Option<unsafe extern "C" fn(*mut c_void, *mut c_void, off_t, size_t)>;
39
40foreign_type! {
41 #[doc(hidden)]
42 pub unsafe type CGDataProvider {
43 type CType = crate::sys::CGDataProvider;
44 fn drop = |cs| CFRelease(cs as *mut _);
45 fn clone = |p| CFRetain(p as *const _) as *mut _;
46 }
47}
48
49impl CGDataProvider {
50 pub fn type_id() -> CFTypeID {
51 unsafe { CGDataProviderGetTypeID() }
52 }
53
54 pub fn from_buffer<T: AsRef<[u8]> + Sync + Send>(buffer: Arc<T>) -> Self {
59 unsafe {
60 let ptr = (*buffer).as_ref().as_ptr() as *const c_void;
61 let len = (*buffer).as_ref().len() as size_t;
62 let info = Arc::into_raw(buffer) as *mut c_void;
63 let result = CGDataProviderCreateWithData(info, ptr, len, Some(release::<T>));
64 return CGDataProvider::from_ptr(result);
65 }
66
67 unsafe extern "C" fn release<T>(info: *mut c_void, _: *const c_void, _: size_t) {
68 drop(Arc::from_raw(info as *mut T))
69 }
70 }
71
72 pub unsafe fn from_slice(buffer: &[u8]) -> Self {
75 let ptr = buffer.as_ptr() as *const c_void;
76 let len = buffer.len() as size_t;
77 let result = CGDataProviderCreateWithData(ptr::null_mut(), ptr, len, None);
78 CGDataProvider::from_ptr(result)
79 }
80
81 pub unsafe fn from_custom_data(custom_data: Box<Box<dyn CustomData>>) -> Self {
86 let (ptr, len) = (custom_data.ptr() as *const c_void, custom_data.len());
87 let userdata = mem::transmute::<Box<Box<dyn CustomData>>, &mut c_void>(custom_data);
88 let data_provider = CGDataProviderCreateWithData(userdata, ptr, len, Some(release));
89 return CGDataProvider::from_ptr(data_provider);
90
91 unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) {
92 drop(mem::transmute::<*mut c_void, Box<Box<dyn CustomData>>>(
93 info,
94 ))
95 }
96 }
97}
98
99impl CGDataProviderRef {
100 pub fn copy_data(&self) -> CFData {
102 unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.as_ptr())) }
103 }
104}
105
106pub trait CustomData {
108 unsafe fn ptr(&self) -> *const u8;
111 unsafe fn len(&self) -> usize;
114}
115
116#[test]
117fn test_data_provider() {
118 let l = vec![5];
119 CGDataProvider::from_buffer(Arc::new(l));
120
121 let l = vec![5];
122 CGDataProvider::from_buffer(Arc::new(l.into_boxed_slice()));
123
124 use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
126 struct VecWrapper {
127 inner: Vec<u8>,
128 dropped: Arc<AtomicBool>,
129 }
130
131 impl Drop for VecWrapper {
132 fn drop(&mut self) {
133 self.dropped.store(true, SeqCst)
134 }
135 }
136
137 impl std::convert::AsRef<[u8]> for VecWrapper {
138 fn as_ref(&self) -> &[u8] {
139 &self.inner
140 }
141 }
142
143 let dropped = Arc::new(AtomicBool::default());
144 let l = Arc::new(VecWrapper {
145 inner: vec![5],
146 dropped: dropped.clone(),
147 });
148 let m = l.clone();
149 let dp = CGDataProvider::from_buffer(l);
150 drop(m);
151 assert!(!dropped.load(SeqCst));
152 drop(dp);
153 assert!(dropped.load(SeqCst))
154}
155
156#[cfg_attr(feature = "link", link(name = "CoreGraphics", kind = "framework"))]
157extern "C" {
158 fn CGDataProviderCopyData(provider: crate::sys::CGDataProviderRef) -> CFDataRef;
159 fn CGDataProviderCreateWithData(
163 info: *mut c_void,
164 data: *const c_void,
165 size: size_t,
166 releaseData: CGDataProviderReleaseDataCallback,
167 ) -> crate::sys::CGDataProviderRef;
168 fn CGDataProviderGetTypeID() -> CFTypeID;
171 }