From 12236ceee70f0f75e8e3f0e00b37ee8c46426eab Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 31 Jul 2018 15:49:40 -0700 Subject: [PATCH] Add the ability to supply custom data to `CGDataProvider`. This is useful for opening memory-mapped files. --- core-graphics/src/data_provider.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core-graphics/src/data_provider.rs b/core-graphics/src/data_provider.rs index 9a50b29..b6388fc 100644 --- a/core-graphics/src/data_provider.rs +++ b/core-graphics/src/data_provider.rs @@ -72,6 +72,21 @@ impl CGDataProvider { 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. + pub unsafe fn from_custom_data(custom_data: Box>) -> Self { + let (ptr, len) = (custom_data.ptr() as *const c_void, custom_data.len()); + let userdata = mem::transmute::>, &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>>(info)) + } + } } impl CGDataProviderRef { @@ -81,6 +96,16 @@ impl CGDataProviderRef { } } +/// Encapsulates custom data that can be wrapped. +pub trait CustomData { + /// Returns a pointer to the start of the custom data. This pointer *must not change* during + /// the lifespan of this CustomData. + unsafe fn ptr(&self) -> *const u8; + /// Returns the length of this custom data. This value must not change during the lifespan of + /// this CustomData. + unsafe fn len(&self) -> usize; +} + #[link(name = "CoreGraphics", kind = "framework")] extern { fn CGDataProviderCopyData(provider: ::sys::CGDataProviderRef) -> CFDataRef;