use crate::constants::LocalAllocFlags;
use std::borrow::{Borrow, BorrowMut};
use std::cmp::PartialEq;
use std::fmt;
use std::hash::Hash;
use std::io;
use std::ops::{Deref, DerefMut};
use std::ptr::{null_mut, NonNull};
pub struct LocalBox<T> {
ptr: NonNull<T>,
}
impl<T> LocalBox<T> {
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
Self { ptr }
}
pub unsafe fn allocate() -> Self {
Self::try_allocate(true, std::mem::size_of::<T>())
.expect("LocalAlloc failed to allocate memory")
}
pub unsafe fn try_allocate(zeroed: bool, size: usize) -> io::Result<Self> {
let flags = match zeroed {
true => LocalAllocFlags::Fixed | LocalAllocFlags::ZeroInit,
false => LocalAllocFlags::Fixed,
};
let ptr = winapi::um::winbase::LocalAlloc(flags.bits(), size);
Ok(Self {
ptr: NonNull::new(ptr as *mut _).ok_or_else(io::Error::last_os_error)?,
})
}
pub fn as_ptr(&self) -> *mut T {
self.ptr.as_ptr()
}
}
impl<T> Drop for LocalBox<T> {
fn drop(&mut self) {
let result = unsafe { winapi::um::winbase::LocalFree(self.as_ptr() as *mut _) };
debug_assert_eq!(result, null_mut());
}
}
impl<T> AsRef<T> for LocalBox<T> {
fn as_ref(&self) -> &T {
&*self
}
}
impl<T> Deref for LocalBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.ptr.as_ref() }
}
}
impl<T> DerefMut for LocalBox<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.ptr.as_mut() }
}
}
impl<T: fmt::Display> fmt::Display for LocalBox<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(fmt)
}
}
impl<T: fmt::Debug> fmt::Debug for LocalBox<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(fmt)
}
}
impl<T> Hash for LocalBox<T>
where
T: Hash,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
impl<T> Borrow<T> for LocalBox<T> {
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T> BorrowMut<T> for LocalBox<T> {
fn borrow_mut(&mut self) -> &mut T {
self.deref_mut()
}
}
impl<T> Eq for LocalBox<T> where T: Eq {}
impl<T, U> PartialEq<LocalBox<U>> for LocalBox<T>
where
T: PartialEq<U>,
{
fn eq(&self, other: &LocalBox<U>) -> bool {
self.deref().eq(other.deref())
}
}
unsafe impl<U: Send> Send for LocalBox<U> {}
unsafe impl<U: Sync> Sync for LocalBox<U> {}