Skip to main content

ratatui_widgets/
as_ref.rs

1/// Implement `AsRef<Self>` for widget types to enable `as_ref()` in generic contexts.
2///
3/// This keeps widget rendering ergonomic when APIs accept `AsRef<WidgetType>` bounds, avoiding
4/// the need for `(&widget).render(...)` just to satisfy a trait bound.
5///
6/// # Example
7///
8/// ```rust
9/// use ratatui_widgets::block::Block;
10///
11/// let block = Block::default();
12/// let block_ref: &Block<'_> = block.as_ref();
13/// ```
14///
15/// # Generated impls
16///
17/// ```rust,ignore
18/// // Non-generic widgets (e.g. Clear, RatatuiLogo).
19/// impl AsRef<Clear> for Clear {
20///     fn as_ref(&self) -> &Clear {
21///         self
22///     }
23/// }
24///
25/// // Generic widgets (e.g. Block with a lifetime, Canvas with a lifetime + type parameter).
26/// impl<'a> AsRef<Block<'a>> for Block<'a> {
27///     fn as_ref(&self) -> &Block<'a> {
28///         self
29///     }
30/// }
31///
32/// impl<'a, F> AsRef<Canvas<'a, F>> for Canvas<'a, F>
33/// where
34///     F: Fn(&mut Context),
35/// {
36///     fn as_ref(&self) -> &Canvas<'a, F> {
37///         self
38///     }
39/// }
40/// ```
41macro_rules! impl_as_ref {
42    ($type:ty, <$($gen:tt),+> $(where $($bounds:tt)+)?) => {
43        impl<$($gen),+> AsRef<$type> for $type $(where $($bounds)+)? {
44            fn as_ref(&self) -> &$type {
45                self
46            }
47        }
48    };
49    ($type:ty) => {
50        impl AsRef<$type> for $type {
51            fn as_ref(&self) -> &$type {
52                self
53            }
54        }
55    };
56}
57
58impl_as_ref!(crate::barchart::BarChart<'a>, <'a>);
59impl_as_ref!(crate::block::Block<'a>, <'a>);
60impl_as_ref!(crate::canvas::Canvas<'a, F>, <'a, F> where F: Fn(&mut crate::canvas::Context));
61impl_as_ref!(crate::chart::Chart<'a>, <'a>);
62impl_as_ref!(crate::clear::Clear);
63impl_as_ref!(crate::gauge::Gauge<'a>, <'a>);
64impl_as_ref!(crate::gauge::LineGauge<'a>, <'a>);
65impl_as_ref!(crate::list::List<'a>, <'a>);
66impl_as_ref!(crate::logo::RatatuiLogo);
67impl_as_ref!(crate::mascot::RatatuiMascot);
68impl_as_ref!(crate::paragraph::Paragraph<'a>, <'a>);
69impl_as_ref!(crate::scrollbar::Scrollbar<'a>, <'a>);
70impl_as_ref!(crate::sparkline::Sparkline<'a>, <'a>);
71impl_as_ref!(crate::table::Table<'a>, <'a>);
72impl_as_ref!(crate::tabs::Tabs<'a>, <'a>);
73#[cfg(feature = "calendar")]
74impl_as_ref!(
75    crate::calendar::Monthly<'a, DS>,
76    <'a, DS> where DS: crate::calendar::DateStyler
77);
78
79#[cfg(test)]
80mod tests {
81    use alloc::vec;
82
83    #[test]
84    fn widgets_implement_as_ref() {
85        let _ = crate::barchart::BarChart::default().as_ref();
86        let _ = crate::block::Block::new().as_ref();
87        let _ = crate::canvas::Canvas::default().paint(|_| {}).as_ref();
88        let _ = crate::chart::Chart::new(vec![]).as_ref();
89        let _ = crate::clear::Clear.as_ref();
90        let _ = crate::gauge::Gauge::default().as_ref();
91        let _ = crate::gauge::LineGauge::default().as_ref();
92        let _ = crate::list::List::new(["foo"]).as_ref();
93        let _ = crate::logo::RatatuiLogo::default().as_ref();
94        let _ = crate::mascot::RatatuiMascot::default().as_ref();
95        let _ = crate::paragraph::Paragraph::new("").as_ref();
96        let _ = crate::scrollbar::Scrollbar::default().as_ref();
97        let _ = crate::sparkline::Sparkline::default().as_ref();
98        let _ = crate::table::Table::default().as_ref();
99        let _ = crate::tabs::Tabs::default().as_ref();
100    }
101
102    #[cfg(feature = "calendar")]
103    #[test]
104    fn calendar_widget_implements_as_ref() {
105        use time::{Date, Month};
106
107        let date = Date::from_calendar_date(2024, Month::January, 1).unwrap();
108        let _ = crate::calendar::Monthly::new(date, crate::calendar::CalendarEventStore::default())
109            .as_ref();
110    }
111}