sauron_core/vdom/attribute/
attribute_value.rs

1use crate::vdom::ComponentEventCallback;
2use crate::{html::attributes::Style, vdom::EventCallback, vdom::Value};
3use derive_where::derive_where;
4
5/// Values of an attribute can be in these variants
6#[derive_where(Clone, Debug)]
7pub enum AttributeValue<MSG> {
8    /// a simple value, wrapper of primitive types
9    Simple(Value),
10    /// style values
11    Style(Vec<Style>),
12    /// Event EventCallback
13    EventListener(EventCallback<MSG>),
14    /// Component Event Listener
15    ComponentEventListener(ComponentEventCallback),
16    /// no value
17    Empty,
18}
19
20/// This is written manually, so we don't push
21/// constraint on MSG to be PartialEq
22/// and also, derive_where can not equate on event listeners
23impl<MSG> PartialEq for AttributeValue<MSG> {
24    fn eq(&self, other: &Self) -> bool {
25        match (self, other) {
26            (AttributeValue::Simple(this), AttributeValue::Simple(other)) => this == other,
27            (AttributeValue::Style(this), AttributeValue::Style(other)) => this == other,
28            (AttributeValue::EventListener(this), AttributeValue::EventListener(other)) => {
29                this == other
30            }
31            (
32                AttributeValue::ComponentEventListener(this),
33                AttributeValue::ComponentEventListener(other),
34            ) => this == other,
35            (AttributeValue::Empty, AttributeValue::Empty) => true,
36            (_, _) => false,
37        }
38    }
39}
40
41impl<MSG> Eq for AttributeValue<MSG> {}
42
43impl<MSG> From<EventCallback<MSG>> for AttributeValue<MSG> {
44    fn from(listener: EventCallback<MSG>) -> Self {
45        Self::EventListener(listener)
46    }
47}
48
49impl<MSG, V> From<V> for AttributeValue<MSG>
50where
51    V: Into<Value>,
52{
53    fn from(v: V) -> Self {
54        Self::Simple(Into::<Value>::into(v))
55    }
56}
57
58impl<MSG> AttributeValue<MSG> {
59    /// create an attribute from Vec<Style>
60    pub fn from_styles(styles: impl IntoIterator<Item = Style>) -> Self {
61        Self::Style(styles.into_iter().collect())
62    }
63
64    /// return the value if it is a Simple variant
65    pub fn get_simple(&self) -> Option<&Value> {
66        match self {
67            Self::Simple(v) => Some(v),
68            _ => None,
69        }
70    }
71
72    /// return the &str value if the value is str value
73    pub fn as_str(&self) -> Option<&str> {
74        if let Some(simple) = self.get_simple() {
75            simple.as_str()
76        } else {
77            None
78        }
79    }
80
81    /// returns true if this attribute value is a style
82    pub fn is_style(&self) -> bool {
83        matches!(self, Self::Style(_))
84    }
85
86    /// return the styles if the attribute value is a style
87    pub fn as_event_listener(&self) -> Option<&EventCallback<MSG>> {
88        match self {
89            Self::EventListener(cb) => Some(cb),
90            _ => None,
91        }
92    }
93
94    /// return true if this is an event listener
95    pub fn is_event_listener(&self) -> bool {
96        matches!(self, Self::EventListener(_))
97    }
98
99    /// return the styles if the attribute value is a style
100    pub fn as_style(&self) -> Option<&Vec<Style>> {
101        match self {
102            Self::Style(styles) => Some(styles),
103            _ => None,
104        }
105    }
106
107    /// returns true if this attribute value is the filler empty attribute
108    pub fn is_just_empty(&self) -> bool {
109        matches!(self, Self::Empty)
110    }
111}