1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
pub mod content;
pub mod image;
pub mod list;
pub mod text;

use crate::widget::{
    node::WidgetNode,
    unit::{content::ContentBox, image::ImageBox, list::ListBox, text::TextBox},
};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WidgetUnit {
    None,
    ContentBox(ContentBox),
    ImageBox(ImageBox),
    TextBox(TextBox),
    ListBox(ListBox),
}

impl Default for WidgetUnit {
    fn default() -> Self {
        Self::None
    }
}

impl WidgetUnit {
    pub fn is_none(&self) -> bool {
        match self {
            Self::None => true,
            _ => false,
        }
    }

    pub fn is_some(&self) -> bool {
        match self {
            Self::None => false,
            _ => true,
        }
    }
}

impl TryFrom<WidgetNode> for WidgetUnit {
    type Error = ();

    fn try_from(node: WidgetNode) -> Result<Self, Self::Error> {
        if let WidgetNode::Unit(v) = node {
            Ok(v)
        } else {
            Err(())
        }
    }
}

impl From<()> for WidgetUnit {
    fn from(_: ()) -> Self {
        Self::None
    }
}

macro_rules! implement_from_unit {
    { $( $type_name:ident ),+ } => {
        $(
            impl From<$type_name> for WidgetUnit {
                fn from(unit: $type_name) -> Self {
                    Self::$type_name(unit)
                }
            }
        )+
    };
}

implement_from_unit! {
    ContentBox,
    ImageBox,
    ListBox,
    TextBox
}