#![warn(rust_2018_idioms, missing_docs)]
#![warn(clippy::dbg_macro, clippy::print_stdout)]
#![doc = include_str!("../README.md")]
#[macro_use]
mod macros;
use phper_sys::*;
use std::{
borrow::Borrow,
convert::TryInto,
mem::{size_of, ManuallyDrop},
ops::{Deref, DerefMut},
};
pub struct EBox<T> {
ptr: *mut T,
}
impl<T> EBox<T> {
#[allow(clippy::useless_conversion)]
pub fn new(x: T) -> Self {
unsafe {
assert_ne!(size_of::<T>(), 0);
let ptr: *mut T = phper_emalloc(size_of::<T>().try_into().unwrap()).cast();
ptr.write(x);
Self { ptr }
}
}
pub unsafe fn from_raw(raw: *mut T) -> Self {
Self { ptr: raw }
}
pub fn into_raw(b: EBox<T>) -> *mut T {
ManuallyDrop::new(b).ptr
}
pub fn into_inner(self) -> T {
unsafe { self.ptr.read() }
}
}
impl<T> Deref for EBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.ptr.as_ref().unwrap() }
}
}
impl<T> DerefMut for EBox<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.ptr.as_mut().unwrap() }
}
}
impl<T> Drop for EBox<T> {
fn drop(&mut self) {
unsafe {
self.ptr.drop_in_place();
phper_efree(self.ptr.cast());
}
}
}
pub trait ToRefOwned {
type Owned: Borrow<Self>;
fn to_ref_owned(&mut self) -> Self::Owned;
}
pub trait RefClone {
fn ref_clone(&mut self) -> Self;
}