Skip to main content

ferroui_base/data/core/plugins/
i_stream_plugin.rs

1use crate::data::core::WeakValue;
2use crate::reactive::{IObservable, Observable};
3use crate::{BoxedValue, PropertyValue};
4use std::rc::Rc;
5
6/// Defines a plugin that handles the `^` stream binding operator.
7pub trait IStreamPlugin {
8    /// Checks whether this plugin handles the specified value.
9    fn match_(&self, reference: &WeakValue) -> bool;
10
11    /// Starts producing output based on the specified value.
12    fn start(&self, reference: &WeakValue) -> Option<Rc<dyn IObservable<Option<BoxedValue>>>>;
13}
14
15/// An observable as a value that can be stored in a property and streamed by
16/// a binding with the `^` operator. It has identity equality.
17#[derive(Clone)]
18pub struct ObservableValue(pub Rc<dyn IObservable<Option<BoxedValue>>>);
19
20impl ObservableValue {
21    /// Wraps a typed observable, boxing each value.
22    pub fn new<T: PropertyValue>(source: Rc<dyn IObservable<T>>) -> Self {
23        use crate::reactive::ObservableExt;
24        Self(source.select(|v| Some(Rc::new(v) as BoxedValue)))
25    }
26}
27
28impl PartialEq for ObservableValue {
29    fn eq(&self, other: &Self) -> bool {
30        Rc::ptr_eq(&self.0, &other.0)
31    }
32}
33
34/// Handles binding to [`ObservableValue`]s for the `^` stream binding
35/// operator.
36pub struct ObservableStreamPlugin;
37
38impl IStreamPlugin for ObservableStreamPlugin {
39    fn match_(&self, reference: &WeakValue) -> bool {
40        reference.upgrade().is_some_and(|t| t.is::<ObservableValue>())
41    }
42
43    fn start(&self, reference: &WeakValue) -> Option<Rc<dyn IObservable<Option<BoxedValue>>>> {
44        match reference.upgrade() {
45            Some(target) => target.downcast_ref::<ObservableValue>().map(|o| o.0.clone()),
46            None => Some(Observable::empty()),
47        }
48    }
49}