mrml/prelude/
mod.rs

1use std::marker::PhantomData;
2
3#[cfg(feature = "json")]
4pub mod json;
5#[cfg(feature = "parse")]
6pub mod parser;
7#[cfg(feature = "print")]
8pub mod print;
9#[cfg(feature = "render")]
10pub mod render;
11
12pub mod hash;
13
14pub trait StaticTag {
15    fn static_tag() -> &'static str;
16}
17
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub struct Component<Tag, Attributes, Children> {
20    pub tag: Tag,
21    pub attributes: Attributes,
22    pub children: Children,
23}
24
25impl<T: Default, A: Default, C: Default> Default for Component<T, A, C> {
26    fn default() -> Self {
27        Self {
28            tag: T::default(),
29            attributes: A::default(),
30            children: C::default(),
31        }
32    }
33}
34
35impl<T, A, C> Component<PhantomData<T>, A, C> {
36    #[inline]
37    pub fn new(attributes: A, children: C) -> Self {
38        Self {
39            tag: PhantomData::<T>,
40            attributes,
41            children,
42        }
43    }
44}
45
46// see https://developer.mozilla.org/en-US/docs/Glossary/Void_element
47#[cfg(any(feature = "parse", feature = "print", feature = "render"))]
48pub(crate) fn is_void_element(tag: &str) -> bool {
49    matches!(
50        tag,
51        "area"
52            | "base"
53            | "br"
54            | "col"
55            | "embed"
56            | "hr"
57            | "img"
58            | "input"
59            | "link"
60            | "meta"
61            | "param"
62            | "source"
63            | "track"
64            | "wbr"
65    )
66}
67
68pub type AttributeMap = hash::Map<String, Option<String>>;
69
70#[derive(Clone, Debug, PartialEq, Eq)]
71#[cfg_attr(feature = "json", derive(serde::Deserialize, serde::Serialize))]
72#[cfg_attr(feature = "json", serde(untagged))]
73pub enum OneOrMany<T> {
74    One(T),
75    Many(Vec<T>),
76}
77
78impl<T> Default for OneOrMany<T> {
79    fn default() -> Self {
80        OneOrMany::Many(Vec::default())
81    }
82}
83
84impl<T> OneOrMany<T> {
85    pub fn iter(&self) -> OneOrManyIter<'_, T> {
86        match self {
87            Self::One(item) => OneOrManyIter::One(std::iter::once(item)),
88            Self::Many(list) => OneOrManyIter::Many(list.iter()),
89        }
90    }
91}
92
93pub enum OneOrManyIter<'a, T> {
94    One(std::iter::Once<&'a T>),
95    Many(std::slice::Iter<'a, T>),
96}
97
98impl<'a, T> Iterator for OneOrManyIter<'a, T> {
99    type Item = &'a T;
100
101    fn next(&mut self) -> Option<Self::Item> {
102        match self {
103            Self::One(inner) => inner.next(),
104            Self::Many(inner) => inner.next(),
105        }
106    }
107}