use core::marker::PhantomData;
pub trait InitSystem {
type Status: Copy;
fn status_initialized() -> Self::Status;
fn status_uninitialized() -> Self::Status;
fn min_align() -> usize;
fn pack(ptr: *mut u8, status: Self::Status) -> usize;
fn unpack_status(packed: usize) -> Self::Status;
fn unpack_ptr(packed: usize) -> *mut u8;
fn init(&self, obj: *mut u8, init_status: Self::Status);
fn drop(obj: *mut u8, init_status: Self::Status);
}
pub struct NopInitSystem;
impl InitSystem for NopInitSystem {
type Status = ();
fn status_initialized() -> () {
()
}
fn status_uninitialized() -> () {
()
}
fn min_align() -> usize {
1
}
fn pack(ptr: *mut u8, _status: ()) -> usize {
ptr as usize
}
fn unpack_status(_packed: usize) -> () {
()
}
fn unpack_ptr(packed: usize) -> *mut u8 {
packed as *mut u8
}
fn init(&self, _obj: *mut u8, _init_status: ()) {}
fn drop(_obj: *mut u8, _init_status: ()) {}
}
pub struct InitInitSystem<T, I: Initializer<T>> {
init: I,
_marker: PhantomData<T>,
}
impl<T, I: Initializer<T>> InitInitSystem<T, I> {
pub fn new(init: I) -> InitInitSystem<T, I> {
InitInitSystem {
init: init,
_marker: PhantomData,
}
}
}
impl<T, I: Initializer<T>> InitSystem for InitInitSystem<T, I> {
type Status = bool;
fn status_initialized() -> bool {
true
}
fn status_uninitialized() -> bool {
false
}
fn min_align() -> usize {
2
}
fn pack(ptr: *mut u8, status: bool) -> usize {
(ptr as usize) | if status { 1 } else { 0 }
}
fn unpack_status(packed: usize) -> bool {
packed & 1 == 1
}
fn unpack_ptr(packed: usize) -> *mut u8 {
(packed & (<usize>::max_value() - 1)) as *mut u8
}
fn init(&self, obj: *mut u8, init: bool) {
if !init {
unsafe {
self.init.init(obj as *mut T);
}
}
}
fn drop(obj: *mut u8, init: bool) {
if init {
unsafe {
use core::ptr::drop_in_place;
drop_in_place(obj as *mut T);
}
}
}
}
pub unsafe trait Initializer<T> {
unsafe fn init(&self, ptr: *mut T);
}
#[derive(Default)]
pub struct DefaultInitializer<T: Default> {
_marker: PhantomData<T>,
}
impl<T: Default> DefaultInitializer<T> {
pub fn new() -> DefaultInitializer<T> {
DefaultInitializer { _marker: PhantomData }
}
}
unsafe impl<T: Default> Initializer<T> for DefaultInitializer<T> {
unsafe fn init(&self, ptr: *mut T) {
use core::ptr::write;
write(ptr, T::default());
}
}
pub struct FnInitializer<T, F: Fn() -> T>(F);
impl<T, F: Fn() -> T> FnInitializer<T, F> {
pub fn new(f: F) -> FnInitializer<T, F> {
FnInitializer(f)
}
}
unsafe impl<T, F: Fn() -> T> Initializer<T> for FnInitializer<T, F> {
unsafe fn init(&self, ptr: *mut T) {
use core::ptr::write;
write(ptr, (self.0)());
}
}
pub struct UnsafeFnInitializer<T, F: Fn(*mut T)>(F, PhantomData<T>);
impl<T, F: Fn(*mut T)> UnsafeFnInitializer<T, F> {
pub fn new(f: F) -> UnsafeFnInitializer<T, F> {
UnsafeFnInitializer(f, PhantomData)
}
}
unsafe impl<T, F: Fn(*mut T)> Initializer<T> for UnsafeFnInitializer<T, F> {
unsafe fn init(&self, ptr: *mut T) {
(self.0)(ptr);
}
}