rtic_macros/syntax/parse/
init.rs

1use crate::syntax::TokenStream2;
2use syn::{parse, ForeignItemFn, ItemFn, Stmt};
3
4use crate::syntax::{
5    ast::{Init, InitArgs},
6    parse::{self as syntax_parse, util},
7};
8
9impl InitArgs {
10    pub(crate) fn parse(tokens: TokenStream2) -> parse::Result<Self> {
11        syntax_parse::init_args(tokens)
12    }
13}
14
15impl Init {
16    pub(crate) fn parse(args: InitArgs, item: ItemFn) -> parse::Result<Self> {
17        let valid_signature = util::check_fn_signature(&item, false) && item.sig.inputs.len() == 1;
18
19        let span = item.sig.ident.span();
20
21        let name = item.sig.ident.to_string();
22
23        if valid_signature {
24            if let Ok((user_shared_struct, user_local_struct)) =
25                util::type_is_init_return(&item.sig.output)
26            {
27                if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
28                    if rest.is_empty() {
29                        return Ok(Init {
30                            args,
31                            attrs: item.attrs,
32                            context,
33                            name: item.sig.ident,
34                            stmts: item.block.stmts,
35                            user_shared_struct,
36                            user_local_struct,
37                            is_extern: false,
38                        });
39                    }
40                }
41            }
42        }
43
44        Err(parse::Error::new(
45            span,
46            format!(
47                "the `#[init]` function must have signature `fn({name}::Context) -> (Shared resources struct, Local resources struct)`"
48            ),
49        ))
50    }
51
52    pub(crate) fn parse_foreign(args: InitArgs, item: ForeignItemFn) -> parse::Result<Self> {
53        let valid_signature =
54            util::check_foreign_fn_signature(&item, false) && item.sig.inputs.len() == 1;
55
56        let span = item.sig.ident.span();
57
58        let name = item.sig.ident.to_string();
59
60        if valid_signature {
61            if let Ok((user_shared_struct, user_local_struct)) =
62                util::type_is_init_return(&item.sig.output)
63            {
64                if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
65                    if rest.is_empty() {
66                        return Ok(Init {
67                            args,
68                            attrs: item.attrs,
69                            context,
70                            name: item.sig.ident,
71                            stmts: Vec::<Stmt>::new(),
72                            user_shared_struct,
73                            user_local_struct,
74                            is_extern: true,
75                        });
76                    }
77                }
78            }
79        }
80
81        Err(parse::Error::new(
82            span,
83            format!(
84                "the `#[init]` function must have signature `fn({name}::Context) -> (Shared resources struct, Local resources struct)`"
85            ),
86        ))
87    }
88}