Skip to main content

ferroui_dynamic_data/
as_disposable.rs

1//! [`AsDisposable`]: the test of upstream's `item as IDisposable`, which `DisposeMany` and
2//! `KeyedDisposable` make of the items they track.
3
4use ferroui_system::IDisposable;
5use std::rc::Rc;
6
7/// An item that may be a disposable (`item as IDisposable`): `DisposeMany` disposes the items for
8/// which [`to_disposable`](AsDisposable::to_disposable) gives a disposable, and leaves the others
9/// alone, as upstream disposes the items that implement `IDisposable`.
10///
11/// Deviation (DEVIATIONS.md, DynamicData): .NET tests the type of an item at run time; Rust has no
12/// such test for a generic item, so the type of the items says whether they are disposable. Every
13/// `Rc` of a disposable is one (`Rc<dyn IDisposable>` and `Rc<X>` for `X: IDisposable`); another
14/// type implements the trait, or `dispose_many_with` takes the function that disposes an item.
15pub trait AsDisposable {
16    /// The item as a disposable, or `None` when it is not one.
17    fn to_disposable(&self) -> Option<Rc<dyn IDisposable>>;
18}
19
20impl AsDisposable for Rc<dyn IDisposable> {
21    fn to_disposable(&self) -> Option<Rc<dyn IDisposable>> {
22        Some(self.clone())
23    }
24}
25
26impl<X: IDisposable + 'static> AsDisposable for Rc<X> {
27    fn to_disposable(&self) -> Option<Rc<dyn IDisposable>> {
28        let disposable: Rc<dyn IDisposable> = self.clone();
29        Some(disposable)
30    }
31}
32
33impl<X: AsDisposable> AsDisposable for Option<X> {
34    fn to_disposable(&self) -> Option<Rc<dyn IDisposable>> {
35        self.as_ref().and_then(AsDisposable::to_disposable)
36    }
37}