use super::{DropFields, MovedOutFields, PrePostDropFields};
use std_::mem::ManuallyDrop;
pub struct IntoFieldsWrapper<T: DropFields> {
value: ManuallyDrop<T>,
moved: MovedOutFields,
}
impl<T: DropFields> IntoFieldsWrapper<T> {
#[inline(always)]
pub fn new(mut value: T) -> Self {
DropFields::pre_move(&mut value);
Self {
value: ManuallyDrop::new(value),
moved: MovedOutFields::new(),
}
}
#[inline(always)]
pub unsafe fn inner_and_moved_mut(&mut self) -> (&mut T, &mut MovedOutFields) {
(&mut self.value, &mut self.moved)
}
#[inline(always)]
pub unsafe fn inner_and_moved_raw(&mut self) -> (*mut T, *mut MovedOutFields) {
(&mut *self.value as *mut T, &mut self.moved as *mut _)
}
}
impl<T: DropFields> Drop for IntoFieldsWrapper<T> {
#[inline(always)]
fn drop(&mut self) {
unsafe {
DropFields::drop_fields(&mut *self.value, self.moved);
}
}
}
macro_rules! declare_run_on_drop {
(
$(#[$meta:meta])*
struct $struct:ident
$(where[$($where_preds:tt)*])?
$(#[$new_meta:meta])*
$(unsafe $(#$dummy:ident#)?)? fn new($($extra_var:ident : $extra_ty:ty),* $(,)?)
this=$this:ident,
fn drop(){$($drop:tt)*}
) => (
$(#[$meta])*
pub struct $struct<'a,T>
$(where $($where_preds)*)?
{
mutref:&'a mut T,
$($extra_var : $extra_ty,)*
}
impl<'a,T> $struct<'a,T>
$(where $($where_preds)*)?
{
$(#[$new_meta])*
#[inline(always)]
pub $(unsafe $(#$dummy#)?)?
fn new(mutref:&'a mut T $(,$extra_var : $extra_ty)*)->Self{
Self{
mutref,
$($extra_var,)*
}
}
#[inline(always)]
pub unsafe fn get_mut(&mut self)->&mut T{
self.mutref
}
}
impl<'a,T> Drop for $struct<'a,T>
$(where $($where_preds)*)?
{
#[inline(always)]
fn drop(&mut self){
let $this=self;
$($drop)*
}
}
)
}
declare_run_on_drop! {
struct RunDrop
unsafe fn new()
this=this,
fn drop(){
unsafe{
std_::ptr::drop_in_place(this.mutref)
}
}
}
declare_run_on_drop! {
struct RunPostDrop
where[ T: PrePostDropFields ]
unsafe fn new()
this=this,
fn drop(){
unsafe{
PrePostDropFields::post_drop(this.mutref)
}
}
}
declare_run_on_drop! {
struct RunDropFields
where[ T: DropFields ]
unsafe fn new(moved: MovedOutFields)
this=this,
fn drop(){
unsafe{
this.mutref.drop_fields(this.moved)
}
}
}
impl<'a, T> RunDropFields<'a, T>
where
T: DropFields,
{
pub unsafe fn get_mut_and_moved_fields(&mut self) -> (&mut T, &mut MovedOutFields) {
(&mut self.mutref, &mut self.moved)
}
}