|
| 1 | +use std::any::TypeId; |
| 2 | +use std::fmt::Debug; |
| 3 | + |
| 4 | +use iced::advanced::graphics::futures::MaybeSend; |
| 5 | + |
| 6 | +// Taken from https://doc.rust-lang.org/stable/src/core/any.rs.html |
| 7 | +// adjusted to fit ReSet |
| 8 | +pub trait ReSetAny: 'static + MaybeSend + Debug + Send + Sync { |
| 9 | + fn type_id(&self) -> TypeId; |
| 10 | +} |
| 11 | + |
| 12 | +impl<T: 'static + ?Sized + Debug + MaybeSend + Send + Sync> ReSetAny for T { |
| 13 | + fn type_id(&self) -> TypeId { |
| 14 | + TypeId::of::<T>() |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +impl dyn ReSetAny { |
| 19 | + #[inline] |
| 20 | + pub fn is<T: ReSetAny>(&self) -> bool { |
| 21 | + // Get `TypeId` of the type this function is instantiated with. |
| 22 | + let t = TypeId::of::<T>(); |
| 23 | + // Get `TypeId` of the type in the trait object (`self`). |
| 24 | + let concrete = self.type_id(); |
| 25 | + // Compare both `TypeId`s on equality. |
| 26 | + t == concrete |
| 27 | + } |
| 28 | + |
| 29 | + #[inline] |
| 30 | + pub fn downcast_ref<T: ReSetAny>(&self) -> Option<&T> { |
| 31 | + if self.is::<T>() { |
| 32 | + // SAFETY: just checked whether we are pointing to the correct type, and we can rely on |
| 33 | + // that check for memory safety because we have implemented Any for all types; no other |
| 34 | + // impls can exist as they would conflict with our impl. |
| 35 | + unsafe { Some(self.downcast_ref_unchecked()) } |
| 36 | + } else { |
| 37 | + None |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + #[inline] |
| 42 | + pub fn downcast_mut<T: ReSetAny>(&mut self) -> Option<&mut T> { |
| 43 | + if self.is::<T>() { |
| 44 | + // SAFETY: just checked whether we are pointing to the correct type, and we can rely on |
| 45 | + // that check for memory safety because we have implemented Any for all types; no other |
| 46 | + // impls can exist as they would conflict with our impl. |
| 47 | + unsafe { Some(self.downcast_mut_unchecked()) } |
| 48 | + } else { |
| 49 | + None |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + #[inline] |
| 54 | + pub unsafe fn downcast_mut_unchecked<T: ReSetAny>(&mut self) -> &mut T { |
| 55 | + debug_assert!(self.is::<T>()); |
| 56 | + // SAFETY: caller guarantees that T is the correct type |
| 57 | + unsafe { &mut *(self as *mut dyn ReSetAny as *mut T) } |
| 58 | + } |
| 59 | + |
| 60 | + #[inline] |
| 61 | + pub unsafe fn downcast_ref_unchecked<T: ReSetAny>(&self) -> &T { |
| 62 | + debug_assert!(self.is::<T>()); |
| 63 | + // SAFETY: caller guarantees that T is the correct type |
| 64 | + unsafe { &*(self as *const dyn ReSetAny as *const T) } |
| 65 | + } |
| 66 | +} |
0 commit comments