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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use core::iter;

use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::token::{Bracket, Colon, Comma, Lt};
use syn::{braced, bracketed, Generics, Ident, Token, Type};

pub struct DelegateComponentsAst {
    pub target_type: Type,
    pub target_generics: Generics,
    pub delegate_entries: DelegateEntriesAst,
}

pub struct DefineComponentsAst {
    pub components_ident: Ident,
    pub components_generics: Generics,
    pub delegate_entries: DelegateEntriesAst,
}

pub struct DelegateEntriesAst {
    pub entries: Punctuated<DelegateEntryAst, Comma>,
}

pub struct DelegateEntryAst {
    pub components: Punctuated<ComponentAst, Comma>,
    pub source: Type,
}

#[derive(Clone)]
pub struct ComponentAst {
    pub component_type: Type,
    pub component_generics: Generics,
}

impl DelegateEntriesAst {
    pub fn all_components(&self) -> Punctuated<ComponentAst, Comma> {
        self.entries
            .iter()
            .flat_map(|entry| entry.components.clone().into_iter())
            .collect()
    }
}

impl Parse for DelegateComponentsAst {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let target_generics = if input.peek(Lt) {
            input.parse()?
        } else {
            Default::default()
        };

        let target_type: Type = input.parse()?;

        let delegate_entries: DelegateEntriesAst = input.parse()?;

        Ok(Self {
            target_type,
            target_generics,
            delegate_entries,
        })
    }
}

impl Parse for DefineComponentsAst {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let components_ident: Ident = input.parse()?;

        let components_generics = if input.peek(Lt) {
            input.parse()?
        } else {
            Default::default()
        };

        let delegate_entries: DelegateEntriesAst = input.parse()?;

        Ok(Self {
            components_ident,
            components_generics,
            delegate_entries,
        })
    }
}

impl Parse for DelegateEntriesAst {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let entries = {
            let entries_body;
            braced!(entries_body in input);
            entries_body.parse_terminated(DelegateEntryAst::parse, Comma)?
        };

        Ok(Self { entries })
    }
}

impl Parse for DelegateEntryAst {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let components = if input.peek(Bracket) {
            let components_body;
            bracketed!(components_body in input);
            components_body.parse_terminated(ComponentAst::parse, Token![,])?
        } else {
            let component: ComponentAst = input.parse()?;
            Punctuated::from_iter(iter::once(component))
        };

        let _: Colon = input.parse()?;

        let source: Type = input.parse()?;

        Ok(Self { components, source })
    }
}

impl Parse for ComponentAst {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let component_generics = if input.peek(Lt) {
            input.parse()?
        } else {
            Default::default()
        };

        let component_type: Type = input.parse()?;

        Ok(Self {
            component_type,
            component_generics,
        })
    }
}

impl ToTokens for ComponentAst {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.extend(self.component_generics.to_token_stream());
        tokens.extend(self.component_type.to_token_stream());
    }
}