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