tag2upload_service_manager/
ui_abstract.rs

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

use crate::prelude::*;

/// Individual values that can be displayed in HTML pages
pub trait UiDisplay {
    fn ui_display(&self) -> Cow<str>;
}

/// Collections of name - value pairs, for HTML pages
pub trait UiMap {
    fn ui_serialize(&self) -> HashMap<&str, Cow<str>> {
        let mut map = HashMap::new();
        map.extend(self.ui_fields());
        map
    }

    fn ui_fields(&self) -> impl Iterator<Item = (&str, Cow<str>)>;
}

pub struct UiSerializeRows<R>(pub Vec<R>);

impl<R: UiMap> Serialize for UiSerializeRows<R> {
    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
        self.0.iter().map(|row| row.ui_serialize())
            .collect_vec()
            .serialize(ser)
    }
}

define_derive_deftly! {
    /// Implement `UiMap`
    ///
    /// Attributess:
    ///  * **`#[deftly(ui(flatten))]`**
    ///  * **`#[deftly(ui(skip))]`**
    UiMap expect items:

    impl $crate::ui_abstract::UiMap for $ttype {
        fn ui_fields(&self) -> impl Iterator<Item = (&str, Cow<str>)> {
            use $crate::ui_abstract::*;

            chain!(
                $(
                    ${select1
                      fmeta(ui(flatten)) {
                          <$ftype as UiMap>::ui_fields(&self.$fname),
                      }
                      fmeta(ui(skip)) {
                      }
                      else {
                          [(
                              stringify!($fname),
                              <$ftype as UiDisplay>::ui_display(&self.$fname),
                          )],
                      }
                    }
                )
            )
        }
    }
}

define_derive_deftly! {
    /// Implement `UiDisplay` for an enum of unit variants
    UiDisplayEnum for enum, expect items:

    impl $crate::ui_abstract::UiDisplay for $ttype {
        fn ui_display(&self) -> Cow<str> {
            match self {
                $(
                    $tname::$vname {} => Cow::Borrowed(stringify!($vname)),
                )
            }
        }
    }
}

impl UiDisplay for String {
    fn ui_display(&self) -> Cow<str> { Cow::Borrowed(self) }
}

impl<T: UiDisplay + SuitableForNoneIsEmpty> UiDisplay for NoneIsEmpty<T> {
    fn ui_display(&self) -> Cow<str> {
        self.as_ref().map(|v| v.ui_display()).unwrap_or_default()
    }
}

impl<T: UiDisplay> UiDisplay for Option<T> {
    fn ui_display(&self) -> Cow<str> {
        self.as_ref().map(|v| v.ui_display()).unwrap_or_default()
    }
}

/// Implement `UiDisplay` in terms of `ToString`
#[macro_export]
macro_rules! ui_display_via_to_string { { $( $ty:ty )* } => { $(
    impl $crate::ui_abstract::UiDisplay for $ty {
        fn ui_display(&self) -> Cow<str> { Cow::Owned(self.to_string()) }
    }
)* } }

ui_display_via_to_string! { i64 }