postcard_bindgen_core/code_gen/
function.rs

1use genco::{lang::Lang, quote, tokens::FormatInto, Tokens};
2
3#[macro_export]
4macro_rules! function_args {
5    ($(($n:expr, $t:expr)),+ $(,)?) => {
6
7        [$(({
8            use genco::tokens::FormatInto;
9            let mut tokens = genco::Tokens::new();
10            $n.format_into(&mut tokens);
11            tokens
12        }, {
13            use genco::tokens::FormatInto;
14            let mut tokens = genco::Tokens::new();
15            $t.format_into(&mut tokens);
16            tokens
17        })),+]
18    };
19    ($($x:expr),+ $(,)?) => {
20
21        [$({
22            use genco::tokens::FormatInto;
23            let mut tokens = genco::Tokens::new();
24            $x.format_into(&mut tokens);
25            tokens
26        }),+]
27    };
28
29}
30
31pub struct FunctionArg<L>
32where
33    L: Lang,
34{
35    pub(super) name: Tokens<L>,
36    pub(super) r#type: Option<Tokens<L>>,
37}
38
39impl<L> FunctionArg<L>
40where
41    L: Lang,
42{
43    pub fn new(name: impl FormatInto<L>, r#type: impl FormatInto<L>) -> Self {
44        Self {
45            name: quote!($name),
46            r#type: Some(quote!($r#type)),
47        }
48    }
49
50    pub fn new_untyped(name: impl FormatInto<L>) -> Self {
51        Self {
52            name: quote!($name),
53            r#type: None,
54        }
55    }
56}
57
58impl<N, T, L> From<(N, T)> for FunctionArg<L>
59where
60    L: Lang,
61    N: FormatInto<L>,
62    T: FormatInto<L>,
63{
64    fn from((name, r#type): (N, T)) -> Self {
65        Self::new(name, r#type)
66    }
67}
68
69impl<L> From<Tokens<L>> for FunctionArg<L>
70where
71    L: Lang,
72{
73    fn from(name: Tokens<L>) -> Self {
74        Self::new_untyped(name)
75    }
76}
77
78pub trait ToArgs<L>
79where
80    L: Lang,
81{
82    fn to_args(self) -> Vec<FunctionArg<L>>;
83}
84
85impl<L, A> ToArgs<L> for Vec<A>
86where
87    L: Lang,
88    A: Into<FunctionArg<L>>,
89{
90    fn to_args(self) -> Vec<FunctionArg<L>> {
91        self.into_iter().map(|a| a.into()).collect()
92    }
93}
94
95impl<L> ToArgs<L> for FunctionArg<L>
96where
97    L: Lang,
98{
99    fn to_args(self) -> Vec<FunctionArg<L>> {
100        vec![self]
101    }
102}
103
104impl<L> ToArgs<L> for ()
105where
106    L: Lang,
107{
108    fn to_args(self) -> Vec<FunctionArg<L>> {
109        Vec::new()
110    }
111}
112
113impl<L, F, const N: usize> ToArgs<L> for [F; N]
114where
115    L: Lang,
116    F: Into<FunctionArg<L>>,
117{
118    fn to_args(self) -> Vec<FunctionArg<L>> {
119        self.into_iter().map(|f| f.into()).collect()
120    }
121}
122
123impl<'a, L, F, const N: usize> ToArgs<L> for &'a [F; N]
124where
125    L: Lang,
126    &'a F: Into<FunctionArg<L>>,
127{
128    fn to_args(self) -> Vec<FunctionArg<L>> {
129        self.iter().map(|f| f.into()).collect()
130    }
131}
132
133pub struct Function<L>
134where
135    L: Lang,
136{
137    pub(super) args: Vec<FunctionArg<L>>,
138    pub(super) name: Tokens<L>,
139    pub(super) body: Tokens<L>,
140    pub(super) return_type: Option<Tokens<L>>,
141    pub(super) doc_string: Option<String>,
142}
143
144impl<L> Function<L>
145where
146    L: Lang,
147{
148    pub fn new(
149        name: impl FormatInto<L>,
150        args: impl ToArgs<L>,
151        body: impl FormatInto<L>,
152        return_type: impl FormatInto<L>,
153    ) -> Self {
154        Self {
155            name: quote!($name),
156            args: args.to_args(),
157            return_type: Some(quote!($return_type)),
158            body: quote!($body),
159            doc_string: None,
160        }
161    }
162
163    pub fn new_untyped(
164        name: impl FormatInto<L>,
165        args: impl ToArgs<L>,
166        body: impl FormatInto<L>,
167    ) -> Self {
168        Self {
169            name: quote!($name),
170            args: args.to_args(),
171            return_type: None,
172            body: quote!($body),
173            doc_string: None,
174        }
175    }
176
177    pub fn with_doc_string(mut self, doc_string: impl ToString) -> Self {
178        self.doc_string = Some(doc_string.to_string());
179        self
180    }
181}