1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
//! Contains the TransparentNewtype trait to enable safer transmutation between types. //! //! # Safety for Users //! //! Given that T impls TransparentNewtype\<Inner=I>. //! //! It is always safe to convert from I to T directly. //! //! It is always safe to convert from pointers to I,eg.:*const I,*mut I,&I,&mut I, to //! pointers to T (the same kind of pointer/reference). //! //! This also includes these smart pointers Box,Rc,Arc in the standard library. //! //! Transmuting a generic type C\<I> to C\<T> is not always safe ,because: //! //! - It may store a `\<I as SomeTrait>::AssocType` instead of storing `I` directly. //! //! - It has to be a type that doesn't change in layout when its type parameter changes. //! //! This has to be evaluated on an individual basis. //! //! # Example //! //! Casting a `[T]` to a `[Wrapper<T>]`,to use its Debug implementation. //! //! ``` //! use core_extensions::{SelfOps,TransparentNewtype}; //! use std::fmt; //! use std::mem::ManuallyDrop; //! //! pub struct DebugFromDisplay<T:?Sized>(pub T); //! //! impl<T:?Sized+fmt::Display> fmt::Debug for DebugFromDisplay<T>{ //! fn fmt(&self,f:&mut fmt::Formatter)->fmt::Result{ //! fmt::Display::fmt(&self.0,f) //! } //! } //! unsafe impl<T:?Sized> TransparentNewtype for DebugFromDisplay<T>{ //! type Inner=T; //! } //! fn slice_as<T>(v:&[T])->&[DebugFromDisplay<T>]{ //! unsafe{ //! let ptr=v.as_ptr() as *const DebugFromDisplay<T>; //! std::slice::from_raw_parts( ptr, v.len() ) //! } //! } //! let list=vec!["\"hello\"","\"world\""]; //! for elem in slice_as(&list) { //! assert_eq!(elem.0,format!("{:?}",elem)); //! } //! //! ``` //! //! # Example //! //! A totally ordered 32 bit float. //! //! ``` //! use core_extensions::{SelfOps,TransparentNewtype}; //! # use std::cmp::{Eq,Ord,PartialOrd,PartialEq,Ordering}; //! //! pub struct TotalF32(pub f32); //! //! //Eq,Ord,PartialEq,PartialOrd impls not shown //! # impl Eq for TotalF32{} //! # //! # impl Ord for TotalF32{ //! # fn cmp(&self, other: &Self) -> Ordering { //! # self.0.partial_cmp(&other.0).unwrap_or_else(||{ //! # match (self.0.is_nan(),other.0.is_nan()) { //! # (false,_ )=>Ordering::Less, //! # (true ,false)=>Ordering::Greater, //! # (true ,true )=>Ordering::Equal, //! # } //! # }) //! # } //! # } //! # impl PartialOrd for TotalF32{ //! # fn partial_cmp(&self, other: &Self) -> Option<Ordering>{ //! # Some(self.cmp(other)) //! # } //! # } //! # impl PartialEq for TotalF32 { //! # fn eq(&self, other: &Self) -> bool { //! # self.cmp(other)==Ordering::Equal //! # } //! # } //! //! unsafe impl TransparentNewtype for TotalF32{ //! type Inner=f32; //! } //! //! fn mut_slice_as(v:&mut [f32])->&mut [TotalF32]{ //! unsafe{ //! let ptr=v.as_mut_ptr() as *mut TotalF32; //! let len=v.len(); //! std::slice::from_raw_parts_mut(ptr,len) //! } //! } //! //! let mut list=vec![1.0,0.0,2.0]; //! //! // This avoids the problem with using sort_by_key , //! // in which the borrow can't be returned from the closure. //! mut_slice_as(&mut list).sort(); //! //! assert_eq!(list,vec![0.0,1.0,2.0]); //! //! ``` use std_::mem; use utils::transmute_ignore_size; /// Trait for `#[repr(transparent)]` newtypes (stable since Rust 1.28) /// which are safe to transmute to/from their contents. /// /// # Safety for users of TransparentNewtype types /// /// Look at the [module-level documentation](index.html#safety-pitfalls) /// pub unsafe trait TransparentNewtype { /// The wrapped type type Inner: ?Sized; /// Converts a T value to Self. #[inline(always)] fn convert_from(v: Self::Inner) -> Self where Self: Sized, Self::Inner: Sized, { check_same_size_alignment::<Self::Inner, Self>(); unsafe { transmute_ignore_size::<Self::Inner, Self>(v) } } /// Converts a reference to T to a reference to Self. #[inline(always)] fn convert_ref_from(v: &Self::Inner) -> &Self { unsafe { transmute_ignore_size(v) } } /// Converts a mutable reference to T to a mutable reference to Self. #[inline(always)] fn convert_mut_from(v: &mut Self::Inner) -> &mut Self { unsafe { transmute_ignore_size(v) } } /// Converts self to a T value. #[inline(always)] fn convert_into(self) -> Self::Inner where Self: Sized, Self::Inner: Sized, { check_same_size_alignment::<Self::Inner, Self>(); unsafe { transmute_ignore_size::<Self, Self::Inner>(self) } } /// Converts a reference to Self to a reference to T. #[inline(always)] fn convert_ref_to(&self) -> &Self::Inner { unsafe { transmute_ignore_size(self) } } /// Converts a mutable reference to Self to a mutable reference to T. #[inline(always)] fn convert_mut_to(&mut self) -> &mut Self::Inner { unsafe { transmute_ignore_size(self) } } } /////////////////////////////////////////////////////////////////////////////// #[inline(always)] fn check_same_size_alignment<T, U>() { assert_eq!(mem::size_of::<T>(), mem::size_of::<U>()); assert_eq!(mem::align_of::<T>(), mem::align_of::<U>()); }