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