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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
/*! <a href="https://github.com/Nercury/typedef-rs"> <img style="position: absolute; top: 0; left: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png" alt="Fork me on GitHub"> </a> <style>.sidebar { margin-top: 53px }</style> */ //! TypeDef is used to identify and compare types, as well as print their names. //! //! If you do not need readable type name, you should use `TypeId`. This //! wrapper re-implements `TypeId`. //! //! To get a name of a type: //! //! ``` //! use typedef::{ TypeDef }; //! //! assert_eq!(TypeDef::name_of::<int>(), "int"); //! ``` //! //! Type can also serve as type identifier and name container: //! //! ``` //! use typedef::{ TypeDef }; //! //! let typedef = TypeDef::of::<int>(); //! //! assert!(typedef.is::<int>()); //! assert_eq!(typedef.get_str(), "int"); //! ``` //! //! More common usage would be in a generic method: //! //! ``` //! use std::fmt::{ Show }; //! use typedef::{ TypeDef }; //! //! fn foo<T: 'static + Show>(value: T) -> String { //! format!( //! "the value of {} type is {}", //! TypeDef::of::<T>(), //! value //! ) //! } //! //! fn main() { //! assert_eq!(foo(15i), "the value of int type is 15"); //! } //! ``` use std::intrinsics::TypeId; use std::intrinsics::get_tydesc; use std::fmt; /// Create a TypeDef structure to identify a type and to print its name. /// /// ``` /// use typedef::{ TypeDef }; /// /// let typedef = TypeDef::of::<int>(); /// /// assert!(typedef.is::<int>()); /// assert!(typedef.get_str() == "int"); /// ``` #[stable] #[deriving(Clone, Copy)] pub struct TypeDef { type_id: TypeId, type_name: &'static str, } #[stable] impl TypeDef { /// Create a TypeDef structure from a type parameter. /// /// ``` /// use typedef::{ TypeDef }; /// /// let typedef = TypeDef::of::<int>(); /// ``` #[stable] pub fn of<T: 'static>() -> TypeDef { TypeDef { type_id: TypeId::of::<T>(), type_name: unsafe { (*get_tydesc::<T>()).name }, } } /// Get `TypeId` for specified type directly. /// /// ``` /// use std::intrinsics::{ TypeId }; /// use typedef::{ TypeDef }; /// /// assert!(TypeDef::id_of::<int>() == TypeId::of::<int>()); /// ``` #[stable] pub fn id_of<T: 'static>() -> TypeId { TypeId::of::<T>() } /// Get type name for specified type directly. /// /// ``` /// use typedef::{ TypeDef }; /// /// assert_eq!(TypeDef::name_of::<int>(), "int"); /// ``` #[stable] pub fn name_of<T: 'static>() -> &'static str { unsafe { (*get_tydesc::<T>()).name } } /// Check if typedef instance matches type. /// /// ``` /// use typedef::{ TypeDef }; /// /// let typedef = TypeDef::of::<int>(); /// /// assert!(typedef.is::<int>()); /// ``` #[stable] pub fn is<T: 'static>(&self) -> bool { self.type_id == TypeId::of::<T>() } /// Get the static `&str` for typedef instance. /// /// ``` /// use typedef::{ TypeDef }; /// /// let typedef = TypeDef::of::<int>(); /// /// assert!(typedef.get_str() == "int"); /// ``` #[stable] pub fn get_str(&self) -> &'static str { self.type_name } } #[stable] impl PartialEq for TypeDef { #[stable] fn eq(&self, other: &TypeDef) -> bool { self.type_id == other.type_id } } #[stable] impl fmt::Show for TypeDef { #[stable] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.type_name) } } #[cfg(test)] mod test { use super::{ TypeDef }; #[test] fn should_match_type() { assert!(TypeDef::of::<i16>().is::<i16>()); } #[test] #[should_fail] fn should_not_match_incorrect_type() { assert!(TypeDef::of::<i16>().is::<i32>()); } #[test] fn should_return_type_name() { assert_eq!(TypeDef::of::<i16>().get_str(), "i16"); assert_eq!(TypeDef::of::<int>().get_str(), "int"); } #[test] fn should_be_equal_to_another_typedef_of_the_same_type() { assert_eq!(TypeDef::of::<i16>(), TypeDef::of::<i16>()); } #[test] fn should_not_be_equal_to_another_typedef_of_different_type() { assert!(TypeDef::of::<i16>() != TypeDef::of::<i32>()); } }