use crate::view::View; use std::any::Any; /// A view that can be downcasted to its concrete type. /// /// This trait is automatically implemented for any `T: View`. pub trait AnyView { /// Downcast self to a `Any`. fn as_any(&self) -> &dyn Any; /// Downcast self to a mutable `Any`. fn as_any_mut(&mut self) -> &mut dyn Any; /// Returns a boxed any from a boxed self. /// /// Can be used before `Box::downcast()`. /// /// # Examples /// /// ```rust /// # use cursive_core::views::TextView; /// # use cursive_core::view::View; /// let boxed: Box = Box::new(TextView::new("text")); /// let text: Box = boxed.as_boxed_any().downcast().unwrap(); /// ``` fn as_boxed_any(self: Box) -> Box; } impl AnyView for T { /// Downcast self to a `Any`. fn as_any(&self) -> &dyn Any { self } /// Downcast self to a mutable `Any`. fn as_any_mut(&mut self) -> &mut dyn Any { self } fn as_boxed_any(self: Box) -> Box { self } } impl dyn AnyView { /// Attempts to downcast `self` to a concrete type. pub fn downcast_ref(&self) -> Option<&T> { self.as_any().downcast_ref() } /// Attempts to downcast `self` to a concrete type. pub fn downcast_mut(&mut self) -> Option<&mut T> { self.as_any_mut().downcast_mut() } /// Attempts to downcast `Box` to a concrete type. pub fn downcast(self: Box) -> Result, Box> { // Do the check here + unwrap, so the error // value is `Self` and not `dyn Any`. if self.as_any().is::() { Ok(self.as_boxed_any().downcast().unwrap()) } else { Err(self) } } /// Checks if this view is of type `T`. pub fn is(&mut self) -> bool { self.as_any().is::() } }