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
use super::*;

#[derive(Default)]
pub(in crate)
struct Args {
    pub(in crate) untyped: Option<Untyped>,
}

pub(in crate)
struct Untyped {
    pub(in crate) _kw: kw::untyped,
}

mod kw {
    ::syn::custom_keyword!(untyped);
}

impl Parse for Args {
    fn parse (
        input: ParseStream<'_>,
    ) -> Result<Args>
    {
        let mut ret = Args::default();
        while input.is_empty().not() {
            let snoopy = input.lookahead1();
            match () {
                | _case if snoopy.peek(kw::untyped) => {
                    if ret.untyped.is_some() {
                        return Err(input.error("duplicate parameter"));
                    }
                    ret.untyped = Some(Untyped {
                        _kw: input.parse().unwrap()
                    });
                },

                | _default => return Err(snoopy.error()),
            }
            let _: Option<Token![,]> = input.parse()?;
        }
        Ok(ret)
    }
}


#[allow(unexpected_cfgs)]
pub(in super)
fn handle (
    Args { untyped }: Args,
    input: ItemConst,
) -> Result<TokenStream2>
{
    if cfg!(feature = "headers").not() {
        Ok(input.into_token_stream())
    } else {
        #[apply(let_quote!)]
        use {
            ::safer_ffi::{
                __cfg_headers__,
                ඞ,
            },
            ::safer_ffi as krate,
        };


        let VAR @ _ = &input.ident;
        let VAR_str @ _ = &VAR.to_string();
        let Ty @ _ = &input.ty;
        let ref each_doc = utils::extract_docs(&input.attrs)?;
        let skip_type = untyped.is_some();

        Ok(quote!(
            #input

            #[cfg(not(target_arch = "wasm32"))]
            #ඞ::inventory::submit! {
                #ඞ::FfiExport {
                    name: #VAR_str,
                    gen_def: |
                        definer: &'_ mut dyn #ඞ::Definer,
                        lang: #ඞ::Language,
                    | {
                        #krate::__with_cfg_python__!(|$if_cfg_python| {
                            use #krate::headers::{
                                Language,
                                languages::{self, HeaderLanguage},
                            };

                            let header_builder: &'static dyn HeaderLanguage = {
                                match lang {
                                    | Language::C => &languages::C,
                                    | Language::CSharp => &languages::CSharp,
                                $($($if_cfg_python)?
                                    | Language::Python => &languages::Python,
                                )?
                                }
                            };

                            <#ඞ::CLayoutOf<#Ty> as #ඞ::CType>::define_self(
                                header_builder,
                                definer
                            )?;

                            header_builder
                        }).emit_constant(
                            definer,
                            &[ #(#each_doc),* ],
                            #VAR_str,
                            &#ඞ::PhantomData::<
                                #ඞ::CLayoutOf< #Ty >,
                            >,
                            #skip_type,
                            &#VAR,
                        )
                    },
                }
            }
        ))
    }
}