use crate::*;
use crate::meta::*;
use super::*;
use winapi::shared::winerror::SUCCEEDED;
use winapi::um::combaseapi::{CoGetMalloc};
use core::mem::MaybeUninit;
use core::ptr::{NonNull, null_mut};
#[doc = include_str!("_refs.md")]
#[derive(Clone)] #[repr(transparent)] pub struct IMalloc(mcom::Rc<winapi::um::objidlbase::IMalloc>);
impl From<mcom::Rc<winapi::um::objidlbase::IMalloc>> for IMalloc { fn from(value: mcom::Rc<winapi::um::objidlbase::IMalloc>) -> Self { Self(value) } }
impl From<IMalloc> for mcom::Rc<winapi::um::objidlbase::IMalloc> { fn from(value: IMalloc) -> Self { value.0 } }
impl TryFrom<CoTaskMem> for IMalloc { fn try_from(_: CoTaskMem) -> Result<Self, Self::Error> { Self::co_get_malloc_1() } type Error = Error; }
impl IMalloc {
#[doc = include_str!("_refs.md")]
pub fn co_get_malloc_1() -> Result<Self, Error> {
let mut result = null_mut();
let hr = unsafe { CoGetMalloc(1, &mut result) };
if !SUCCEEDED(hr) { return Err(Error(winresult::ErrorHResultOrCode::from(hr))) }
Ok(Self(unsafe { mcom::Rc::from_raw(result) }))
}
pub fn did_alloc(&self, ptr: *mut MaybeUninit<u8>) -> Option<bool> {
match unsafe { self.0.DidAlloc(ptr.cast()) } {
1 => Some(true),
0 => Some(false),
-1 => None,
_ => None, }
}
pub fn heap_minimize(&self) {
unsafe { self.0.HeapMinimize() }
}
}
impl Meta for IMalloc {
type Error = ();
const MIN_ALIGN : Alignment = super::MEMORY_ALLOCATION_ALIGNMENT; const MAX_ALIGN : Alignment = super::MEMORY_ALLOCATION_ALIGNMENT; const MAX_SIZE : usize = usize::MAX;
const ZST_SUPPORTED : bool = true;
}
impl ZstSupported for IMalloc {}
#[doc = include_str!("_refs.md")]
unsafe impl thin::Alloc for IMalloc {
fn alloc_uninit(&self, size: usize) -> Result<AllocNN, Self::Error> {
let alloc = unsafe { self.0.Alloc(size) };
NonNull::new(alloc.cast()).ok_or(())
}
}
#[doc = include_str!("_refs.md")]
#[allow(clippy::missing_safety_doc)]
unsafe impl thin::Realloc for IMalloc {
const CAN_REALLOC_ZEROED : bool = false;
unsafe fn realloc_uninit(&self, ptr: AllocNN, new_size: usize) -> Result<AllocNN, Self::Error> {
if new_size == 0 {
let alloc = thin::Alloc::alloc_uninit(self, new_size)?;
unsafe { thin::Free::free(self, ptr) };
Ok(alloc)
} else {
let alloc = unsafe { self.0.Realloc(ptr.as_ptr().cast(), new_size) };
NonNull::new(alloc.cast()).ok_or(())
}
}
unsafe fn realloc_zeroed(&self, _ptr: AllocNN, _new_size: usize) -> Result<AllocNN, Self::Error> {
Err(())
}
}
#[doc = include_str!("_refs.md")]
#[allow(clippy::missing_safety_doc)]
unsafe impl thin::Free for IMalloc {
unsafe fn free_nullable(&self, ptr: *mut MaybeUninit<u8>) {
unsafe { self.0.Free(ptr.cast()) }
}
}
#[doc = include_str!("_refs.md")]
#[allow(clippy::missing_safety_doc)]
unsafe impl thin::SizeOfDebug for IMalloc {
unsafe fn size_of_debug(&self, ptr: NonNull<MaybeUninit<u8>>) -> Option<usize> {
match unsafe { self.0.GetSize(ptr.as_ptr().cast()) } {
usize::MAX => None,
size => Some(size),
}
}
}
unsafe impl thin::SizeOf for IMalloc {}
#[no_implicit_prelude] mod cleanroom {
use super::{impls, IMalloc};
impls! {
unsafe impl ialloc::fat::Alloc for IMalloc => ialloc::thin::Alloc;
unsafe impl ialloc::fat::Realloc for IMalloc => ialloc::thin::Realloc;
unsafe impl ialloc::fat::Free for IMalloc => ialloc::thin::Free;
}
}
#[test] fn thin_alignment() { thin::test::alignment(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_edge_case_sizes() { thin::test::edge_case_sizes(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_nullable() { thin::test::nullable(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_size() { thin::test::size_exact_alloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_uninit() { unsafe { thin::test::uninit_alloc_unsound(IMalloc::co_get_malloc_1().unwrap()) } }
#[test] fn thin_uninit_realloc() { thin::test::uninit_realloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_zeroed() { thin::test::zeroed_alloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_zeroed_realloc() { thin::test::zeroed_realloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn thin_zst_support() { thin::test::zst_supported_accurate(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn fat_alignment() { fat::test::alignment(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn fat_edge_case_sizes() { fat::test::edge_case_sizes(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn fat_uninit() { unsafe { fat::test::uninit_alloc_unsound(IMalloc::co_get_malloc_1().unwrap()) } }
#[test] fn fat_uninit_realloc() { fat::test::uninit_realloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn fat_zeroed() { fat::test::zeroed_alloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn fat_zeroed_realloc() { fat::test::zeroed_realloc(IMalloc::co_get_malloc_1().unwrap()) }
#[test] fn fat_zst_support() { fat::test::zst_supported_accurate(IMalloc::co_get_malloc_1().unwrap()) }