// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
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;
/// Creates a data provider from the given reference-counted buffer. /// /// The `CGDataProvider` object takes ownership of the reference. Once the data provider /// is destroyed, the reference count of the buffer is automatically decremented. pubfn 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);
}
/// Creates a data prvider from a given slice. The data provider does not own the slice in this /// case, so it's up to the user to ensure the memory safety here. pubunsafefn 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)
}
/// Creates a data provider from the given raw pointer, length, and destructor function. /// /// This is double-boxed because the Core Text API requires that the userdata be a single /// pointer. pubunsafefn 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);
impl CGDataProviderRef { /// Creates a copy of the data from the underlying `CFDataProviderRef`. pubfn copy_data(&self) -> CFData { unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.as_ptr())) }
}
}
/// Encapsulates custom data that can be wrapped. pubtrait CustomData { /// Returns a pointer to the start of the custom data. This pointer *must not change* during /// the lifespan of this CustomData. unsafefn ptr(&self) -> *const u8; /// Returns the length of this custom data. This value must not change during the lifespan of /// this CustomData. unsafefn 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()));
// Make sure the buffer is actually dropped use std::sync::atomic::{AtomicBool, Ordering::SeqCst}; struct VecWrapper {
inner: Vec<u8>,
dropped: Arc<AtomicBool>,
}
impl Drop for VecWrapper { fn drop(&mutself) { self.dropped.store(true, SeqCst)
}
}
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))
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.