Skip to content

Instantly share code, notes, and snippets.

@Connicpu
Created November 11, 2018 00:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Connicpu/7d423cac145f98cb354b8278efd2a1df to your computer and use it in GitHub Desktop.
Save Connicpu/7d423cac145f98cb354b8278efd2a1df to your computer and use it in GitHub Desktop.
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)]
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]
unsafe 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
}
}
pub mod file_stream {
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)]
pub struct FileStream {
vtbl: VTable<IDWriteFontFileStreamVtbl>,
refcount: Refcount,
write_time: u64,
file_data: Vec<u8>,
}
impl FileStream {
fn create_raw(write_time: u64, file_data: Vec<u8>) -> *mut Self {
Box::into_raw(Box::new(FileStream {
vtbl: <Self as com_impl::BuildVTable<_>>::static_vtable(),
refcount: Default::default(),
write_time: write_time,
file_data: 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 static_vtable() -> com_impl::VTable<winapi::um::unknwnbase::IUnknownVtbl> {
com_impl::VTable::new(&Self::VTBL)
}
}
#[allow(non_snake_case)]
impl FileStream {
#[inline(never)]
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()
}
#[inline(never)]
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 {
Box::from_raw(ptr);
}
count
}
#[inline(never)]
unsafe extern "system" fn __com_impl__IUnknown__QueryInterface(
this: *mut winapi::um::unknwnbase::IUnknown,
riid: *const winapi::shared::guiddef::IID,
ppv: *mut *mut winapi::ctypes::c_void,
) -> winapi::shared::winerror::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 winapi::ctypes::c_void;
winapi::shared::winerror::S_OK
} else {
*ppv = std::ptr::null_mut();
winapi::shared::winerror::E_NOINTERFACE
}
}
}
impl FileStream {
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) }
}
}
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 static_vtable() -> com_impl::VTable<IDWriteFontFileStreamVtbl> {
com_impl::VTable::new(&Self::VTBL)
}
}
#[allow(non_snake_case)]
impl FileStream {
#[inline(never)]
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__GetFileSize(
this: *mut IDWriteFontFileStream,
__com_arg_0: *mut u64,
) -> HRESULT {
let this = &*(this as *const Self);
Self::__com_impl_body__IDWriteFontFileStream__GetFileSize(this, __com_arg_0)
}
#[inline(never)]
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__GetLastWriteTime(
this: *mut IDWriteFontFileStream,
__com_arg_0: *mut u64,
) -> HRESULT {
let this = &*(this as *const Self);
Self::__com_impl_body__IDWriteFontFileStream__GetLastWriteTime(this, __com_arg_0)
}
#[inline(never)]
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__ReadFileFragment(
this: *mut IDWriteFontFileStream,
__com_arg_0: *mut *const c_void,
__com_arg_1: u64,
__com_arg_2: u64,
__com_arg_3: *mut *mut c_void,
) -> HRESULT {
let this = &*(this as *const Self);
Self::__com_impl_body__IDWriteFontFileStream__ReadFileFragment(
this,
__com_arg_0,
__com_arg_1,
__com_arg_2,
__com_arg_3,
)
}
#[inline(never)]
unsafe extern "system" fn __com_impl_stub__IDWriteFontFileStream__ReleaseFileFragment(
this: *mut IDWriteFontFileStream,
__com_arg_0: *mut c_void,
) {
let this = &*(this as *const Self);
Self::__com_impl_body__IDWriteFontFileStream__ReleaseFileFragment(this, __com_arg_0)
}
#[inline(always)]
unsafe extern "system" fn __com_impl_body__IDWriteFontFileStream__GetFileSize(
&self,
size: *mut u64,
) -> HRESULT {
*size = self.file_data.len() as u64;
S_OK
}
#[inline(always)]
unsafe extern "system" fn __com_impl_body__IDWriteFontFileStream__GetLastWriteTime(
&self,
write_time: *mut u64,
) -> HRESULT {
*write_time = self.write_time;
S_OK
}
#[inline(always)]
unsafe extern "system" 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
}
#[inline(always)]
unsafe extern "system" fn __com_impl_body__IDWriteFontFileStream__ReleaseFileFragment(
&self,
_ctx: *mut c_void,
) {
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment