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
//! # trapper //! //! Trapper (or transparent wrapper) allows for the creation of transparent type wrappers, //! that is types which are transparent and can be wrapped and unwrapped for zero cost. extern crate self as trapper; /// A type wrapper. This trait provides methods for converting between a wrapper and its /// inner type. It should only be implemented by types through the `newtype` macro. If it must /// be implemented manually, the type should have transparent representation to be safe. pub unsafe trait Wrapper: Sized { /// The inner wrapped type type Inner: Sized; /// Wraps the value, returning a new instance of the wrapper. /// /// # Example /// /// ``` /// use trapper::{Wrapper, newtype}; /// newtype!(#[derive(PartialEq, Debug)] type NumberWrapper(i32)); /// /// # fn main() { /// let wrapper = NumberWrapper::wrap(12); /// let other = NumberWrapper::wrap(12); /// assert_eq!(wrapper, other); /// # } /// ``` fn wrap(inner: Self::Inner) -> Self; /// Unwraps the wrapper, returning its inner value. /// /// # Example /// /// ``` /// use trapper::{Wrapper, newtype}; /// newtype!(type NumberWrapper(i32)); /// /// # fn main() { /// let wrapper = NumberWrapper::wrap(12); /// assert_eq!(wrapper.unwrap(), 12); /// # } /// ``` fn unwrap(self) -> Self::Inner; /// Wraps a shared reference to the value in the wrapper type /// /// # Example /// /// ``` /// use trapper::{Wrapper, newtype}; /// newtype!(type NumberWrapper(i32)); /// /// # fn main() { /// let number = 12; /// let wrapper: &NumberWrapper = NumberWrapper::wrap_ref(&number); /// # } /// ``` fn wrap_ref(inner: &Self::Inner) -> &Self { unsafe { &*(inner as *const Self::Inner as *const Self) } } /// Wraps a unique reference to the value in the wrapper type /// /// # Example /// /// ``` /// use trapper::{Wrapper, newtype}; /// newtype!(type NumberWrapper(i32)); /// /// # fn main() { /// let mut number = 12; /// let wrapper: &mut NumberWrapper = NumberWrapper::wrap_mut(&mut number); /// *wrapper = NumberWrapper::wrap(13); /// /// assert_eq!(number, 13); /// # } /// ``` fn wrap_mut(inner: &mut Self::Inner) -> &mut Self { unsafe { &mut *(inner as *mut Self::Inner as *mut Self) } } /// Unwraps a shared reference to the wrapper, exposing the underlying type /// /// # Example /// /// ``` /// use trapper::{Wrapper, newtype}; /// newtype!(type NumberWrapper(i32)); /// /// # fn main() { /// let wrapper = NumberWrapper::wrap(12); /// /// assert_eq!(*wrapper.unwrap_ref(), 12); /// # } /// ``` fn unwrap_ref(&self) -> &Self::Inner { unsafe { &*(self as *const Self as *const Self::Inner) } } /// Unwraps a unique reference to the wrapper, exposing the underlying type /// /// # Example /// /// ``` /// use trapper::{Wrapper, newtype}; /// newtype!(#[derive(PartialEq, Debug)] type NumberWrapper(i32)); /// /// # fn main() { /// let mut wrapper = NumberWrapper::wrap(12); /// *wrapper.unwrap_mut() = 13; /// /// assert_eq!(wrapper, NumberWrapper::wrap(13)); /// # } /// ``` fn unwrap_mut(&mut self) -> &mut Self::Inner { unsafe { &mut *(self as *mut Self as *mut Self::Inner) } } } pub use trapper_macro::newtype; #[cfg(test)] mod tests { use super::newtype; newtype!(#[allow(dead_code)] type InMod(i32)); newtype!(#[allow(dead_code)] type WithLifetimes<'a>(std::io::StderrLock<'a>)); newtype!(#[allow(dead_code)] type WithTypeParameters<T>(T)); newtype!(#[allow(dead_code)] type WithBoth<'a, T>(&'a T)); newtype!(#[allow(dead_code)] type WithClause<'a, T>(&'a T) where T: Default); newtype! { #[allow(dead_code)] /// doc type AttributesDocsLifetimesTypesClausesTrailingSemicolon<'a, 'b, 'c, T>(&'a &'b &'c T) where T: Default + Clone, 'a: 'b; } newtype! { type NoWhereClause<'a: 'b, 'b, T = i32>(&'b &'a T); } }