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}