Last active
November 10, 2018 16:37
-
-
Save Connicpu/be60a51331558f51ce5563a5c23828fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate derive_com_impl; | |
extern crate com_impl; | |
extern crate winapi; | |
extern crate wio; | |
use com_impl::{Refcount, VTable}; | |
use winapi::ctypes::c_void; | |
use winapi::shared::winerror::{ERROR_INVALID_INDEX, HRESULT, HRESULT_FROM_WIN32, S_OK}; | |
use winapi::um::dwrite::{IDWriteFontFileStream, IDWriteFontFileStreamVtbl}; | |
use wio::com::ComPtr; | |
#[repr(C)] | |
#[derive(ComImpl)] | |
#[interfaces(IDWriteFontFileStream)] | |
pub struct FileStream { | |
vtbl: VTable<IDWriteFontFileStreamVtbl>, | |
refcount: Refcount, | |
write_time: u64, | |
file_data: Vec<u8>, | |
} | |
impl FileStream { | |
// Todo: Use a wrapper type for the ComPtr | |
pub fn new(write_time: u64, data: Vec<u8>) -> ComPtr<IDWriteFontFileStream> { | |
let ptr = FileStream::create_raw(write_time, data); | |
let ptr = ptr as *mut IDWriteFontFileStream; | |
unsafe { ComPtr::from_raw(ptr) } | |
} | |
} | |
#[com_impl] | |
impl IDWriteFontFileStream for FileStream { | |
unsafe fn get_file_size(&self, size: *mut u64) -> HRESULT { | |
*size = self.file_data.len() as u64; | |
S_OK | |
} | |
unsafe fn get_last_write_time(&self, write_time: *mut u64) -> HRESULT { | |
*write_time = self.write_time; | |
S_OK | |
} | |
unsafe fn read_file_fragment( | |
&self, | |
start: *mut *const c_void, | |
offset: u64, | |
size: u64, | |
ctx: *mut *mut c_void, | |
) -> HRESULT { | |
if offset > std::isize::MAX as u64 || size > std::isize::MAX as u64 { | |
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); | |
} | |
let offset = offset as usize; | |
let size = size as usize; | |
if offset + size > self.file_data.len() { | |
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); | |
} | |
*start = self.file_data.as_ptr().offset(offset as isize) as *const c_void; | |
*ctx = std::ptr::null_mut(); | |
S_OK | |
} | |
unsafe fn release_file_fragment(&self, _ctx: *mut c_void) { | |
// Nothing to do | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Mock-up output | |
// ---------------------------------------------- | |
// Begin derive(ComImpl) | |
// ---------------------------------------------- | |
impl FileStream { | |
fn create_raw(write_time: u64, file_data: Vec<u8>) -> *mut FileStream { | |
Box::into_raw(Box::new(FileStream { | |
vtbl: <Self as com_impl::BuildVTable<_>>::build_vtable(), | |
refcount: Default::default(), | |
write_time, | |
file_data, | |
})) | |
} | |
} | |
unsafe impl com_impl::BuildVTable<winapi::um::unknwnbase::IUnknownVtbl> for FileStream { | |
const VTBL: winapi::um::unknwnbase::IUnknownVtbl = winapi::um::unknwnbase::IUnknownVtbl { | |
AddRef: Self::__com_impl__IUnknown__AddRef, | |
Release: Self::__com_impl__IUnknown__Release, | |
QueryInterface: Self::__com_impl__IUnknown__QueryInterface, | |
}; | |
fn build_vtable() -> com_impl::VTable<winapi::um::unknwnbase::IUnknownVtbl> { | |
com_impl::VTable::new(&Self::VTBL) | |
} | |
} | |
#[allow(non_snake_case)] | |
impl FileStream { | |
unsafe extern "system" fn __com_impl__IUnknown__AddRef( | |
this: *mut winapi::um::unknwnbase::IUnknown, | |
) -> u32 { | |
let this = &*(this as *const Self); | |
this.refcount.add_ref() | |
} | |
unsafe extern "system" fn __com_impl__IUnknown__Release( | |
this: *mut winapi::um::unknwnbase::IUnknown, | |
) -> u32 { | |
let ptr = this as *mut Self; | |
let count = (*ptr).refcount.release(); | |
if count == 0 { | |
// This was the last ref | |
Box::from_raw(ptr); | |
} | |
count | |
} | |
unsafe extern "system" fn __com_impl__IUnknown__QueryInterface( | |
this: *mut winapi::um::unknwnbase::IUnknown, | |
riid: *const winapi::shared::guiddef::IID, | |
ppv: *mut *mut c_void, | |
) -> HRESULT { | |
if ppv.is_null() { | |
return winapi::shared::winerror::E_POINTER; | |
} | |
if winapi::shared::guiddef::IsEqualIID( | |
&*riid, | |
&<winapi::um::unknwnbase::IUnknown as winapi::Interface>::uuidof(), | |
) || winapi::shared::guiddef::IsEqualIID( | |
&*riid, | |
&<IDWriteFontFileStream as winapi::Interface>::uuidof(), | |
) { | |
*ppv = this as *mut c_void; | |
winapi::shared::winerror::S_OK | |
} else { | |
*ppv = std::ptr::null_mut(); | |
winapi::shared::winerror::E_NOINTERFACE | |
} | |
} | |
} | |
// ---------------------------------------------- | |
// End derive(ComImpl) | |
// ---------------------------------------------- | |
// ---------------------------------------------- | |
// Begin com_impl | |
// ---------------------------------------------- | |
unsafe impl com_impl::BuildVTable<IDWriteFontFileStreamVtbl> for FileStream { | |
const VTBL: IDWriteFontFileStreamVtbl = IDWriteFontFileStreamVtbl { | |
parent: <Self as com_impl::BuildVTable<_>>::VTBL, | |
GetFileSize: Self::__com_impl_stub__IDWriteFontFileStream__GetFileSize, | |
GetLastWriteTime: Self::__com_impl_stub__IDWriteFontFileStream__GetLastWriteTime, | |
ReadFileFragment: Self::__com_impl_stub__IDWriteFontFileStream__ReadFileFragment, | |
ReleaseFileFragment: Self::__com_impl_stub__IDWriteFontFileStream__ReleaseFileFragment, | |
}; | |
fn build_vtable() -> com_impl::VTable<IDWriteFontFileStreamVtbl> { | |
com_impl::VTable::new(&Self::VTBL) | |
} | |
} | |
#[allow(non_snake_case)] | |
impl FileStream { | |
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__GetFileSize( | |
this: *mut IDWriteFontFileStream, | |
size: *mut u64, | |
) -> HRESULT { | |
let this = &*(this as *const Self); | |
this.__com_impl_body__IDWriteFontFileStream__GetFileSize(size) | |
} | |
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__GetLastWriteTime( | |
this: *mut IDWriteFontFileStream, | |
write_time: *mut u64, | |
) -> HRESULT { | |
let this = &*(this as *const Self); | |
this.__com_impl_body__IDWriteFontFileStream__GetLastWriteTime(write_time) | |
} | |
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__ReadFileFragment( | |
this: *mut IDWriteFontFileStream, | |
start: *mut *const c_void, | |
offset: u64, | |
size: u64, | |
ctx: *mut *mut c_void, | |
) -> HRESULT { | |
let this = &*(this as *const Self); | |
this.__com_impl_body__IDWriteFontFileStream__ReadFileFragment(start, offset, size, ctx) | |
} | |
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__ReleaseFileFragment( | |
this: *mut IDWriteFontFileStream, | |
_ctx: *mut c_void, | |
) { | |
let this = &*(this as *const Self); | |
this.__com_impl_body__IDWriteFontFileStream__ReleaseFileFragment(_ctx) | |
} | |
unsafe fn __com_impl_body__IDWriteFontFileStream__GetFileSize( | |
&self, | |
size: *mut u64, | |
) -> HRESULT { | |
*size = self.file_data.len() as u64; | |
S_OK | |
} | |
unsafe fn __com_impl_body__IDWriteFontFileStream__GetLastWriteTime( | |
&self, | |
write_time: *mut u64, | |
) -> HRESULT { | |
*write_time = self.write_time; | |
S_OK | |
} | |
unsafe fn __com_impl_body__IDWriteFontFileStream__ReadFileFragment( | |
&self, | |
start: *mut *const c_void, | |
offset: u64, | |
size: u64, | |
ctx: *mut *mut c_void, | |
) -> HRESULT { | |
if offset > std::isize::MAX as u64 || size > std::isize::MAX as u64 { | |
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); | |
} | |
let offset = offset as usize; | |
let size = size as usize; | |
if offset + size > self.file_data.len() { | |
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); | |
} | |
*start = self.file_data.as_ptr().offset(offset as isize) as *const c_void; | |
*ctx = std::ptr::null_mut(); | |
S_OK | |
} | |
unsafe fn __com_impl_body__IDWriteFontFileStream__ReleaseFileFragment( | |
&self, | |
_ctx: *mut c_void, | |
) { | |
// Nothing to do | |
} | |
} | |
// ---------------------------------------------- | |
// End com_impl | |
// ---------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment