use std::boxed::Box;
use std::ops::{Deref,DerefMut};
use std::convert::AsRef;
use std::borrow::Borrow;
use super::*;
pub enum ZeroDropCow<'a, T: Copy + 'a> {
Borrowed(&'a T),
Boxed(Box<T>),
}
impl<'a, T> Drop for ZeroDropCow<'a, T> where T: 'a+Copy {
#[inline(never)]
fn drop(&mut self) {
match *self {
ZeroDropCow::Borrowed(_) => { },
ZeroDropCow::Boxed(ref mut b) => {
let s: &mut T = b.deref_mut();
unsafe { ::std::intrinsics::volatile_set_memory::<T>(s,0,1) }
}
}
}
}
impl<'a, T> ZeroDropCow<'a, T> where T: 'a+Copy {
pub fn new_insecure(t: T) -> ZeroDropCow<'a,T> {
ZeroDropCow::Boxed(Box::new(t))
}
pub unsafe fn new_uninitialized() -> ZeroDropCow<'a,T> {
ZeroDropCow::Boxed(Box::new(::std::mem::uninitialized::<T>()))
}
pub fn new(t: &'a T) -> ZeroDropCow<'a,T> {
ZeroDropCow::Borrowed(t)
}
pub fn new_copy(t: &T) -> ZeroDropCow<'a,T> {
let mut b = Box::new(unsafe { ::std::mem::uninitialized::<T>() });
unsafe { ::std::ptr::copy_nonoverlapping::<T>(t,b.deref_mut(),1) }
ZeroDropCow::Boxed(b)
}
pub fn into_boxed(mut self) -> ZeroDrop<T> {
match self {
ZeroDropCow::Borrowed(b) => ZeroDrop::new_copy(b),
ZeroDropCow::Boxed(ref mut o) => {
let mut b = Box::new(unsafe { ::std::mem::uninitialized::<T>() });
::std::mem::swap::<T>(o,&mut b);
ZeroDrop::new_box(b)
}
}
}
}
impl<'a, T> Default for ZeroDropCow<'a, T> where T: 'a+Copy+Default {
fn default() -> ZeroDropCow<'a, T> {
ZeroDropCow::Boxed(Default::default())
}
}
impl<'a, T> Clone for ZeroDropCow<'a, T> where T: 'a+Copy {
fn clone(&self) -> ZeroDropCow<'a, T> {
use self::ZeroDropCow::*;
match *self {
Borrowed(b) => Borrowed(b),
Boxed(ref o) => ZeroDropCow::new_copy(o.deref()),
}
}
}
impl<'a, T> Deref for ZeroDropCow<'a, T> where T: 'a+Copy {
type Target = T;
fn deref(&self) -> &T {
use self::ZeroDropCow::*;
match *self {
Borrowed(b) => b,
Boxed(ref o) => o.deref(), }
}
}
impl<'a, T> AsRef<T> for ZeroDropCow<'a, T> where T: 'a+Copy {
fn as_ref(&self) -> &T {
use self::ZeroDropCow::*;
match *self {
Borrowed(b) => b,
Boxed(ref o) => o.as_ref(),
}
}
}
impl<'a, T> Borrow<T> for ZeroDropCow<'a, T> where T: 'a+Copy {
fn borrow(&self) -> &T {
use self::ZeroDropCow::*;
match *self {
Borrowed(b) => b,
Boxed(ref o) => o.borrow(),
}
}
}