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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// printing.rs requires #specialization to detect if type implements Debug or Display
// to provide some printing capabilities to all types.
#![cfg_attr(feature = "printing", feature(specialization))]

#[cfg(feature = "phlow-derive")]
pub use phlow_derive::{extensions, view};

pub extern crate log;

pub use crate::meta::*;
pub use crate::object::*;
pub use crate::printing::*;
pub use crate::reflection::*;
pub use crate::views::*;

mod meta;
mod object;
mod printing;
mod reflection;
mod views;

pub trait Phlow<Category> {
    fn phlow_view_methods(extension: &PhlowExtension) -> Vec<PhlowViewMethod>;
    fn phlow_extension() -> Option<PhlowExtension>;
}

impl<Category, T> Phlow<Category> for T {
    default fn phlow_view_methods(_extension: &PhlowExtension) -> Vec<PhlowViewMethod> {
        vec![]
    }
    default fn phlow_extension() -> Option<PhlowExtension> {
        None
    }
}

#[macro_export]
macro_rules! phlow {
    ($var:expr) => {{
        phlow::PhlowObject::object($var, crate::phlow_extensions_of_val)
    }};
    ($var:expr, <$($generic_type:ident),+>) => {{
        phlow::PhlowObject::object_with_generics(
            $var,
            crate::phlow_extensions_of_val,
            vec![
                $(
                    phlow::PhlowType::new::<$generic_type>(crate::phlow_extensions::<$generic_type>)
                )+
            ])
    }};
    (&$var:expr, $parent:expr) => {{
        phlow::PhlowObject::reference(&$var, $parent, crate::phlow_extensions_of_val)
    }};
    ($var:expr, $parent:expr) => {{
        phlow::PhlowObject::reference($var, $parent, crate::phlow_extensions_of_val)
    }};
}

#[macro_export]
macro_rules! phlow_generic {
    ($child:expr, $parent:expr) => {{
        phlow::PhlowObject::construct_reference(
            $child,
            $parent
                .generic_phlow_type(0)
                .unwrap_or_else(|| phlow_type!($child)),
            Some($parent.clone()),
        )
    }};
}

#[macro_export]
macro_rules! phlow_type {
    ($var:expr) => {{
        phlow::PhlowType::of($var, crate::phlow_extensions_of_val)
    }};
}

#[macro_export]
macro_rules! phlow_all {
    ($iter:expr) => {{
        $iter
            .into_iter()
            .map(|each| phlow!(each))
            .collect::<Vec<phlow::PhlowObject>>()
    }};
}

#[macro_export]
macro_rules! define_extensions {
    ($e:ident) => {
        pub struct $e;
    };
}

#[macro_export]
macro_rules! import_extensions {
    ($($es:ident),*) => {
        pub(crate) fn phlow_extensions_of_val<T: 'static>(_value: &T) -> Vec<phlow::PhlowExtension> {
            phlow_extensions::<T>()
        }
        pub(crate) fn phlow_extensions<T: 'static>() -> Vec<phlow::PhlowExtension> {
            let mut extensions = vec![];
            $(
                if let Some(extension) = <T as phlow::Phlow::<$es>>::phlow_extension() {
                    extensions.push(extension);
                }
            )*
            extensions
        }
        pub(crate) fn phlow_view_methods<T: 'static>(value: &T) -> Vec<phlow::PhlowViewMethod> {
            phlow_extensions_of_val(value)
                .into_iter()
                .map(|extension| extension.view_methods())
                .flatten()
                .collect()
        }
    };
}