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>());
}