core_graphics2/
data_provider.rs1use std::{ffi::CString, ptr::null_mut, sync::Arc};
2
3use core_foundation::{
4 base::{CFTypeID, TCFType},
5 data::{CFData, CFDataRef},
6 impl_CFTypeDescription, impl_TCFType,
7 url::{CFURLRef, CFURL},
8};
9use libc::{c_char, c_void, off_t, size_t};
10
11#[repr(C)]
12pub struct __CGDataProvider(c_void);
13
14pub type CGDataProviderRef = *const __CGDataProvider;
15
16pub type CGDataProviderGetBytesCallback = extern "C" fn(*mut c_void, *mut c_void, size_t) -> size_t;
17pub type CGDataProviderSkipForwardCallback = extern "C" fn(*mut c_void, off_t) -> off_t;
18pub type CGDataProviderRewindCallback = extern "C" fn(*mut c_void);
19pub type CGDataProviderReleaseInfoCallback = extern "C" fn(*mut c_void);
20
21#[repr(C)]
22pub struct CGDataProviderSequentialCallbacks {
23 pub version: u32,
24 pub getBytes: CGDataProviderGetBytesCallback,
25 pub skipForward: CGDataProviderSkipForwardCallback,
26 pub rewind: CGDataProviderRewindCallback,
27 pub releaseInfo: CGDataProviderReleaseInfoCallback,
28}
29
30pub type CGDataProviderGetBytePointerCallback = extern "C" fn(*mut c_void) -> *mut c_void;
31pub type CGDataProviderReleaseBytePointerCallback = extern "C" fn(*mut c_void, *const c_void);
32pub type CGDataProviderGetBytesAtPositionCallback = extern "C" fn(*mut c_void, *mut c_void, off_t, size_t);
33
34#[repr(C)]
35pub struct CGDataProviderDirectCallbacks {
36 pub version: u32,
37 pub getBytePointer: CGDataProviderGetBytePointerCallback,
38 pub releaseBytePointer: CGDataProviderReleaseBytePointerCallback,
39 pub getBytesAtPosition: CGDataProviderGetBytesAtPositionCallback,
40 pub releaseInfo: CGDataProviderReleaseInfoCallback,
41}
42
43pub type CGDataProviderReleaseDataCallback = extern "C" fn(*mut c_void, *const c_void, size_t);
44
45extern "C" {
46 pub fn CGDataProviderGetTypeID() -> CFTypeID;
47 pub fn CGDataProviderCreateSequential(info: *mut c_void, callbacks: *const CGDataProviderSequentialCallbacks) -> CGDataProviderRef;
48 pub fn CGDataProviderCreateDirect(info: *mut c_void, size: off_t, callbacks: *const CGDataProviderDirectCallbacks) -> CGDataProviderRef;
49 pub fn CGDataProviderCreateWithData(
50 info: *mut c_void,
51 data: *const c_void,
52 size: size_t,
53 releaseData: Option<CGDataProviderReleaseDataCallback>,
54 ) -> CGDataProviderRef;
55 pub fn CGDataProviderCreateWithCFData(data: CFDataRef) -> CGDataProviderRef;
56 pub fn CGDataProviderCreateWithURL(url: CFURLRef) -> CGDataProviderRef;
57 pub fn CGDataProviderCreateWithFilename(filename: *const c_char) -> CGDataProviderRef;
58 pub fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef;
59 pub fn CGDataProviderRelease(provider: CGDataProviderRef);
60 pub fn CGDataProviderCopyData(provider: CGDataProviderRef) -> CFDataRef;
61 pub fn CGDataProviderGetInfo(provider: CGDataProviderRef) -> *mut c_void;
62}
63
64pub struct CGDataProvider(CGDataProviderRef);
65
66impl Drop for CGDataProvider {
67 fn drop(&mut self) {
68 unsafe { CGDataProviderRelease(self.0) }
69 }
70}
71
72impl_TCFType!(CGDataProvider, CGDataProviderRef, CGDataProviderGetTypeID);
73impl_CFTypeDescription!(CGDataProvider);
74
75impl CGDataProvider {
76 pub unsafe fn new_sequential(info: *mut c_void, callbacks: *const CGDataProviderSequentialCallbacks) -> Option<Self> {
77 let provider = CGDataProviderCreateSequential(info, callbacks);
78 if provider.is_null() {
79 None
80 } else {
81 Some(TCFType::wrap_under_create_rule(provider))
82 }
83 }
84
85 pub unsafe fn new_direct(info: *mut c_void, size: off_t, callbacks: *const CGDataProviderDirectCallbacks) -> Option<Self> {
86 let provider = CGDataProviderCreateDirect(info, size, callbacks);
87 if provider.is_null() {
88 None
89 } else {
90 Some(TCFType::wrap_under_create_rule(provider))
91 }
92 }
93
94 pub fn from_buffer<T>(buffer: Arc<T>) -> Option<Self>
95 where
96 T: AsRef<[u8]> + Sync + Send,
97 {
98 unsafe {
99 let ptr = (*buffer).as_ref().as_ptr() as *const c_void;
100 let len = (*buffer).as_ref().len() as size_t;
101 let info = Arc::into_raw(buffer) as *mut c_void;
102 let data_provider = CGDataProviderCreateWithData(info, ptr, len, Some(release::<T>));
103 if data_provider.is_null() {
104 drop(Arc::from_raw(info));
105 return None;
106 } else {
107 return Some(TCFType::wrap_under_create_rule(data_provider));
108 }
109 }
110
111 extern "C" fn release<T>(info: *mut c_void, _: *const c_void, _: size_t) {
112 unsafe { drop(Arc::from_raw(info as *mut T)) }
113 }
114 }
115
116 pub unsafe fn from_slice(buffer: &[u8]) -> Option<Self> {
117 let ptr = buffer.as_ptr() as *const c_void;
118 let len = buffer.len() as size_t;
119 let data_provider = CGDataProviderCreateWithData(null_mut(), ptr, len, None);
120 if data_provider.is_null() {
121 None
122 } else {
123 Some(TCFType::wrap_under_create_rule(data_provider))
124 }
125 }
126
127 pub fn from_data(data: &CFData) -> Option<Self> {
128 unsafe {
129 let data_provider = CGDataProviderCreateWithCFData(data.as_concrete_TypeRef());
130 if data_provider.is_null() {
131 None
132 } else {
133 Some(TCFType::wrap_under_create_rule(data_provider))
134 }
135 }
136 }
137
138 pub fn from_url(url: CFURL) -> Option<Self> {
139 unsafe {
140 let data_provider = CGDataProviderCreateWithURL(url.as_concrete_TypeRef());
141 if data_provider.is_null() {
142 None
143 } else {
144 Some(TCFType::wrap_under_create_rule(data_provider))
145 }
146 }
147 }
148
149 pub fn from_filename(filename: &str) -> Option<Self> {
150 let c_str = CString::new(filename).ok()?;
151 unsafe {
152 let data_provider = CGDataProviderCreateWithFilename(c_str.as_ptr() as *const c_char);
153 if data_provider.is_null() {
154 None
155 } else {
156 Some(TCFType::wrap_under_create_rule(data_provider))
157 }
158 }
159 }
160
161 pub fn copy_data(&self) -> Option<CFData> {
162 unsafe {
163 let data = CGDataProviderCopyData(self.as_concrete_TypeRef());
164 if data.is_null() {
165 None
166 } else {
167 Some(TCFType::wrap_under_create_rule(data))
168 }
169 }
170 }
171
172 pub unsafe fn get_info(&self) -> *mut c_void {
173 unsafe { CGDataProviderGetInfo(self.as_concrete_TypeRef()) }
174 }
175}