1use crate::dom::StatefulModel;
3use crate::dom::StatelessModel;
4use crate::vdom::Attribute;
5use crate::vdom::AttributeName;
6use crate::vdom::AttributeValue;
7use crate::vdom::Node;
8use crate::vdom::TemplatedView;
9use derive_where::derive_where;
10use std::borrow::Cow;
11
12#[derive_where(Clone, Debug)]
14pub enum Leaf<MSG> {
15    Text(Cow<'static, str>),
17    Symbol(Cow<'static, str>),
19    Comment(Cow<'static, str>),
21    DocType(Cow<'static, str>),
24    NodeList(Vec<Node<MSG>>),
27    Fragment(Vec<Node<MSG>>),
29    #[cfg(feature = "with-dom")]
31    StatefulComponent(StatefulModel<MSG>),
32    StatelessComponent(StatelessModel<MSG>),
34    TemplatedView(TemplatedView<MSG>),
36}
37
38impl<MSG> PartialEq for Leaf<MSG> {
39    fn eq(&self, other: &Self) -> bool {
40        match (self, other) {
41            (Self::Text(v), Self::Text(o)) => v == o,
42            (Self::Symbol(v), Self::Symbol(o)) => v == o,
43            (Self::Comment(v), Self::Comment(o)) => v == o,
44            (Self::DocType(v), Self::DocType(o)) => v == o,
45            (Self::NodeList(v), Self::NodeList(o)) => v == o,
46            (Self::Fragment(v), Self::Fragment(o)) => v == o,
47            #[cfg(feature = "with-dom")]
48            (Self::StatefulComponent(v), Self::StatefulComponent(o)) => v == o,
49            (Self::StatelessComponent(v), Self::StatelessComponent(o)) => v == o,
50            _ => false,
51        }
52    }
53}
54
55impl<MSG> Eq for Leaf<MSG> {}
56
57impl<MSG> Leaf<MSG> {
58    pub fn is_text(&self) -> bool {
60        matches!(self, Self::Text(_))
61    }
62
63    pub fn as_text(&self) -> Option<&str> {
65        match self {
66            Self::Text(ref text) => Some(text),
67            _ => None,
68        }
69    }
70
71    pub fn attribute_value(&self, name: &AttributeName) -> Option<Vec<&AttributeValue<MSG>>> {
73        match self {
74            Self::StatelessComponent(comp) => comp.attribute_value(name),
75            Self::TemplatedView(templated_view) => templated_view.view.attribute_value(name),
76            _ => None,
77        }
78    }
79
80    pub fn attributes(&self) -> Option<&[Attribute<MSG>]> {
83        match self {
84            Self::StatelessComponent(comp) => comp.attributes(),
85            Self::TemplatedView(templated_view) => templated_view.view.attributes(),
86            _ => None,
87        }
88    }
89}
90
91impl<MSG> From<&'static str> for Leaf<MSG> {
92    fn from(s: &'static str) -> Self {
93        Self::Text(Cow::from(s))
94    }
95}
96
97impl<MSG> From<String> for Leaf<MSG> {
98    fn from(s: String) -> Self {
99        Self::Text(Cow::from(s))
100    }
101}