1 #![cfg_attr(not(feature = "std"), no_std)] 2 3 #[cfg(not(feature = "std"))] 4 mod std { 5 pub use core::*; 6 } 7 8 use std::any::{Any as StdAny, TypeId, type_name}; 9 use std::fmt::{self, Debug, Display}; 10 11 #[cfg(feature = "std")] 12 use std::{error::Error, rc::Rc, sync::Arc}; 13 14 // ++++++++++++++++++++ Any ++++++++++++++++++++ 15 16 pub trait Any: StdAny { 17 #[doc(hidden)] as_any(&self) -> &dyn StdAny18 fn as_any(&self) -> &dyn StdAny; 19 20 #[doc(hidden)] as_any_mut(&mut self) -> &mut dyn StdAny21 fn as_any_mut(&mut self) -> &mut dyn StdAny; 22 23 #[doc(hidden)] 24 #[cfg(feature = "std")] into_any(self: Box<Self>) -> Box<dyn StdAny>25 fn into_any(self: Box<Self>) -> Box<dyn StdAny>; 26 27 #[doc(hidden)] 28 #[cfg(feature = "std")] into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny>29 fn into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny>; 30 type_name(&self) -> &'static str31 fn type_name(&self) -> &'static str; 32 } 33 34 impl<T> Any for T where T: StdAny { 35 #[doc(hidden)] as_any(&self) -> &dyn StdAny36 fn as_any(&self) -> &dyn StdAny { self } 37 38 #[doc(hidden)] as_any_mut(&mut self) -> &mut dyn StdAny39 fn as_any_mut(&mut self) -> &mut dyn StdAny { self } 40 41 #[cfg(feature = "std")] into_any(self: Box<Self>) -> Box<dyn StdAny>42 fn into_any(self: Box<Self>) -> Box<dyn StdAny> { self } 43 44 #[cfg(feature = "std")] into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny>45 fn into_any_rc(self: Rc<Self>) -> Rc<dyn StdAny> { self } 46 type_name(&self) -> &'static str47 fn type_name(&self) -> &'static str { type_name::<Self>() } 48 } 49 50 #[cfg(feature = "std")] 51 pub trait AnySync: Any + Send + Sync { into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync>52 fn into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync>; 53 } 54 55 #[cfg(feature = "std")] 56 impl<T> AnySync for T where T: Any + Send + Sync { into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync>57 fn into_any_arc(self: Arc<Self>) -> Arc<dyn StdAny + Send + Sync> { self } 58 } 59 60 // ++++++++++++++++++++ TypeMismatch ++++++++++++++++++++ 61 62 #[derive(Debug, Clone, Copy)] 63 pub struct TypeMismatch { 64 pub expected: &'static str, 65 pub found: &'static str, 66 } 67 68 impl TypeMismatch { new<T, O>(found_obj: &O) -> Self where T: Any + ?Sized, O: Any + ?Sized69 pub fn new<T, O>(found_obj: &O) -> Self 70 where T: Any + ?Sized, O: Any + ?Sized 71 { 72 TypeMismatch { 73 expected: type_name::<T>(), 74 found: found_obj.type_name(), 75 } 76 } 77 } 78 79 impl Display for TypeMismatch { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result80 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 81 write!(fmt, "Type mismatch: Expected '{}', found '{}'!", self.expected, self.found) 82 } 83 } 84 85 #[cfg(feature = "std")] 86 impl Error for TypeMismatch {} 87 88 // ++++++++++++++++++++ DowncastError ++++++++++++++++++++ 89 90 pub struct DowncastError<O> { 91 mismatch: TypeMismatch, 92 object: O, 93 } 94 95 impl<O> DowncastError<O> { new(mismatch: TypeMismatch, object: O) -> Self96 pub fn new(mismatch: TypeMismatch, object: O) -> Self { 97 Self{ mismatch, object } 98 } type_mismatch(&self) -> TypeMismatch99 pub fn type_mismatch(&self) -> TypeMismatch { self.mismatch } into_object(self) -> O100 pub fn into_object(self) -> O { self.object } 101 } 102 103 impl<O> Debug for DowncastError<O> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result104 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 105 fmt.debug_struct("DowncastError") 106 .field("mismatch", &self.mismatch) 107 .finish() 108 } 109 } 110 111 impl<O> Display for DowncastError<O> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result112 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 113 Display::fmt(&self.mismatch, fmt) 114 } 115 } 116 117 #[cfg(feature = "std")] 118 impl<O> Error for DowncastError<O> {} 119 120 // ++++++++++++++++++++ Downcast ++++++++++++++++++++ 121 122 pub trait Downcast<T>: Any 123 where T: Any 124 { is_type(&self) -> bool125 fn is_type(&self) -> bool { self.type_id() == TypeId::of::<T>() } 126 downcast_ref(&self) -> Result<&T, TypeMismatch>127 fn downcast_ref(&self) -> Result<&T, TypeMismatch> { 128 if self.is_type() { 129 Ok(self.as_any().downcast_ref().unwrap()) 130 } else { 131 Err(TypeMismatch::new::<T, Self>(self)) 132 } 133 } 134 downcast_mut(&mut self) -> Result<&mut T, TypeMismatch>135 fn downcast_mut(&mut self) -> Result<&mut T, TypeMismatch> { 136 if self.is_type() { 137 Ok(self.as_any_mut().downcast_mut().unwrap()) 138 } else { 139 Err(TypeMismatch::new::<T, Self>(self)) 140 } 141 } 142 143 #[cfg(feature = "std")] downcast(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<Self>>>144 fn downcast(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<Self>>> { 145 if self.is_type() { 146 Ok(self.into_any().downcast().unwrap()) 147 } else { 148 let mismatch = TypeMismatch::new::<T, Self>(&*self); 149 Err(DowncastError::new(mismatch, self)) 150 } 151 } 152 153 #[cfg(feature = "std")] downcast_rc(self: Rc<Self>) -> Result<Rc<T>, DowncastError<Rc<Self>>>154 fn downcast_rc(self: Rc<Self>) -> Result<Rc<T>, DowncastError<Rc<Self>>> { 155 if self.is_type() { 156 Ok(self.into_any_rc().downcast().unwrap()) 157 } else { 158 let mismatch = TypeMismatch::new::<T, Self>(&*self); 159 Err(DowncastError::new(mismatch, self)) 160 } 161 } 162 } 163 164 #[cfg(feature = "std")] 165 pub trait DowncastSync<T>: Downcast<T> + AnySync 166 where T: AnySync 167 { downcast_arc(self: Arc<Self>) -> Result<Arc<T>, DowncastError<Arc<Self>>>168 fn downcast_arc(self: Arc<Self>) -> Result<Arc<T>, DowncastError<Arc<Self>>> { 169 if self.is_type() { 170 Ok(self.into_any_arc().downcast().unwrap()) 171 } else { 172 let mismatch = TypeMismatch::new::<T, Self>(&*self); 173 Err(DowncastError::new(mismatch, self)) 174 } 175 } 176 } 177 178 // ++++++++++++++++++++ macros ++++++++++++++++++++ 179 180 #[doc(hidden)] 181 pub mod _std { 182 #[cfg(feature = "std")] 183 pub use std::*; 184 #[cfg(not(feature = "std"))] 185 pub use core::*; 186 } 187 188 /// Implements [`Downcast`](trait.Downcast.html) for your trait-object-type. 189 /// 190 /// ```ignore 191 /// impl_downcast!(Foo); 192 /// impl_downcast!(<B> Foo<B> where B: Bar); 193 /// impl_downcast!(<B> Foo<Bar = B>); 194 /// ``` 195 /// 196 /// expands to 197 /// 198 /// ```ignore 199 /// impl<T> Downcast<T> for Foo 200 /// where T: Any 201 /// {} 202 /// 203 /// impl<T, B> Downcast<T> for Foo<B> 204 /// where T: Any, B: Bar 205 /// {} 206 /// 207 /// impl<T, B> Downcast<T> for Foo<Bar = B> 208 /// where T: Any 209 /// {} 210 /// ``` 211 #[macro_export] 212 macro_rules! impl_downcast { 213 (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => { 214 impl<_T, $($params),+> $crate::Downcast<_T> for $base 215 where _T: $crate::Any, $($params: 'static,)* $($($bounds)+)* 216 {} 217 }; 218 ($base:ty) => { 219 impl<_T> $crate::Downcast<_T> for $base 220 where _T: $crate::Any 221 {} 222 }; 223 } 224 225 /// Implements [`Downcast`](trait.Downcast.html) and [`DowncastSync`](trait.DowncastSync.html) for your trait-object-type. 226 #[cfg(feature = "std")] 227 #[macro_export] 228 macro_rules! impl_downcast_sync { 229 (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => { 230 impl<_T, $($params),+> $crate::Downcast<_T> for $base 231 where _T: $crate::Any, $($params: 'static,)* $($($bounds)+)* 232 {} 233 234 impl<_T, $($params),+> $crate::DowncastSync<_T> for $base 235 where _T: $crate::AnySync, $($params: 'static,)* $($($bounds)+)* 236 {} 237 }; 238 ($base:ty) => { 239 impl<_T> $crate::Downcast<_T> for $base 240 where _T: $crate::Any 241 {} 242 243 impl<_T> $crate::DowncastSync<_T> for $base 244 where _T: $crate::AnySync 245 {} 246 }; 247 } 248 249 #[doc(hidden)] 250 #[macro_export] 251 macro_rules! downcast_methods_core { 252 (@items) => { 253 #[allow(unused, missing_docs)] 254 pub fn is<_T>(&self) -> bool 255 where _T: $crate::Any, Self: $crate::Downcast<_T> 256 { 257 $crate::Downcast::<_T>::is_type(self) 258 } 259 260 #[allow(unused, missing_docs)] 261 pub fn downcast_ref<_T>(&self) -> $crate::_std::result::Result<&_T, $crate::TypeMismatch> 262 where _T: $crate::Any, Self: $crate::Downcast<_T> 263 { 264 $crate::Downcast::<_T>::downcast_ref(self) 265 } 266 267 #[allow(unused, missing_docs)] 268 pub fn downcast_mut<_T>(&mut self) -> $crate::_std::result::Result<&mut _T, $crate::TypeMismatch> 269 where _T: $crate::Any, Self: $crate::Downcast<_T> 270 { 271 $crate::Downcast::<_T>::downcast_mut(self) 272 } 273 }; 274 (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => { 275 impl<$($params),+> $base 276 where $($params: 'static,)* $($($bounds)+)* 277 { 278 $crate::downcast_methods_core!(@items); 279 } 280 }; 281 ($base:ty) => { 282 impl $base { 283 $crate::downcast_methods_core!(@items); 284 } 285 }; 286 } 287 288 #[doc(hidden)] 289 #[macro_export] 290 macro_rules! downcast_methods_std { 291 (@items) => { 292 $crate::downcast_methods_core!(@items); 293 294 #[allow(unused, missing_docs)] 295 pub fn downcast<_T>(self: $crate::_std::boxed::Box<Self>) -> $crate::_std::result::Result<$crate::_std::boxed::Box<_T>, $crate::DowncastError<$crate::_std::boxed::Box<Self>>> 296 where _T: $crate::Any, Self: $crate::Downcast<_T> 297 { 298 $crate::Downcast::<_T>::downcast(self) 299 } 300 301 #[allow(unused, missing_docs)] 302 pub fn downcast_rc<_T>(self: $crate::_std::rc::Rc<Self>) -> $crate::_std::result::Result<$crate::_std::rc::Rc<_T>, $crate::DowncastError<$crate::_std::rc::Rc<Self>>> 303 where _T: $crate::Any, Self: $crate::Downcast<_T> 304 { 305 $crate::Downcast::<_T>::downcast_rc(self) 306 } 307 }; 308 (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => { 309 impl<$($params),+> $base 310 $(where $($bounds)+)* 311 { 312 $crate::downcast_methods_std!(@items); 313 } 314 }; 315 ($base:ty) => { 316 impl $base { 317 $crate::downcast_methods_std!(@items); 318 } 319 }; 320 } 321 322 #[doc(hidden)] 323 #[cfg(feature = "std")] 324 #[macro_export] 325 macro_rules! downcast_sync_methods { 326 (@items) => { 327 $crate::downcast_methods_std!(@items); 328 329 #[allow(unused, missing_docs)] 330 pub fn downcast_arc<_T>(self: $crate::_std::sync::Arc<Self>) -> $crate::_std::result::Result<$crate::_std::sync::Arc<_T>, $crate::DowncastError<$crate::_std::sync::Arc<Self>>> 331 where _T: $crate::AnySync, Self: $crate::DowncastSync<_T> 332 { 333 $crate::DowncastSync::<_T>::downcast_arc(self) 334 } 335 }; 336 (<$($params:ident),+ $(,)*> $base:ty $(where $($bounds:tt)+)*) => { 337 impl<$($params),+> $base 338 $(where $($bounds)+)* 339 { 340 $crate::downcast_sync_methods!(@items); 341 } 342 }; 343 ($base:ty) => { 344 impl $base { 345 $crate::downcast_sync_methods!(@items); 346 } 347 }; 348 } 349 350 351 /// Generate `downcast`-methods for your trait-object-type. 352 /// 353 /// ```ignore 354 /// downcast_methods!(Foo); 355 /// downcast_methods!(<B> Foo<B> where B: Bar); 356 /// downcast_methods!(<B> Foo<Bar = B>); 357 /// ``` 358 /// 359 /// ```ignore 360 /// impl dyn Foo { 361 /// /* impl<B> dyn Foo<B> where B: Bar { */ 362 /// /* impl<B> dyn Foo<Bar = B> { */ 363 /// 364 /// pub fn is<T>(&self) -> bool 365 /// where T: Any, Self: Downcast<T> 366 /// { ... } 367 /// 368 /// pub fn downcast_ref<T>(&self) -> Result<&T, TypeMismatch> 369 /// where T: Any, Self: Downcast<T> 370 /// { ... } 371 /// 372 /// pub fn downcast_mut<T>(&mut self) -> Result<&mut T, TypeMismatch> 373 /// where T: Any, Self: Downcast<T> 374 /// { ... } 375 /// } 376 /// ``` 377 #[cfg(not(feature = "std"))] 378 #[macro_export] 379 macro_rules! downcast_methods { 380 ($($tt:tt)+) => { $crate::downcast_methods_core!($($tt)+); } 381 } 382 383 /// Generate `downcast`-methods for your trait-object-type. 384 /// 385 /// ```ignore 386 /// downcast_methods!(Foo); 387 /// downcast_methods!(<B> Foo<B> where B: Bar); 388 /// downcast_methods!(<B> Foo<Bar = B>); 389 /// ``` 390 /// 391 /// ```ignore 392 /// impl dyn Foo { 393 /// /* impl<B> dyn Foo<B> where B: Bar { */ 394 /// /* impl<B> dyn Foo<Bar = B> { */ 395 /// 396 /// pub fn is<T>(&self) -> bool 397 /// where T: Any, Self: Downcast<T> 398 /// { ... } 399 /// 400 /// pub fn downcast_ref<T>(&self) -> Result<&T, TypeMismatch> 401 /// where T: Any, Self: Downcast<T> 402 /// { ... } 403 /// 404 /// pub fn downcast_mut<T>(&mut self) -> Result<&mut T, TypeMismatch> 405 /// where T: Any, Self: Downcast<T> 406 /// { ... } 407 /// 408 /// pub fn downcast<T>(self: Box<Self>) -> Result<Box<T>, DowncastError<Box<T>>> 409 /// where T: Any, Self: Downcast<T> 410 /// { ... } 411 /// } 412 /// ``` 413 #[cfg(feature = "std")] 414 #[macro_export] 415 macro_rules! downcast_methods { 416 ($($tt:tt)+) => { $crate::downcast_methods_std!($($tt)+); } 417 } 418 419 /// Implements [`Downcast`](trait.Downcast.html) and generates 420 /// `downcast`-methods for your trait-object-type. 421 /// 422 /// See [`impl_downcast`](macro.impl_downcast.html), 423 /// [`downcast_methods`](macro.downcast_methods.html). 424 #[macro_export] 425 macro_rules! downcast { 426 ($($tt:tt)+) => { 427 $crate::impl_downcast!($($tt)+); 428 $crate::downcast_methods!($($tt)+); 429 } 430 } 431 432 /// Implements [`DowncastSync`](trait.DowncastSync.html) and generates 433 /// `downcast`-methods for your trait-object-type. 434 /// 435 /// See [`impl_downcast_sync`](macro.impl_downcast.html), 436 /// [`downcast_sync_methods`](macro.downcast_methods.html). 437 #[cfg(feature = "std")] 438 #[macro_export] 439 macro_rules! downcast_sync { 440 ($($tt:tt)+) => { 441 $crate::impl_downcast_sync!($($tt)+); 442 $crate::downcast_sync_methods!($($tt)+); 443 } 444 } 445 446 // NOTE: We only implement the trait, because implementing the methods won't 447 // be possible when we replace downcast::Any by std::any::Any. 448 downcast!(dyn Any); 449 downcast!((dyn Any + Send)); 450 downcast!((dyn Any + Sync)); 451 #[cfg(feature = "std")] 452 downcast_sync!(dyn AnySync); 453 454