rtic_macros/syntax/parse/
idle.rs

1use proc_macro2::TokenStream as TokenStream2;
2use syn::{parse, ForeignItemFn, ItemFn, Stmt};
3
4use crate::syntax::{
5    ast::{Idle, IdleArgs},
6    parse::util,
7};
8
9impl IdleArgs {
10    pub(crate) fn parse(tokens: TokenStream2) -> parse::Result<Self> {
11        crate::syntax::parse::idle_args(tokens)
12    }
13}
14
15impl Idle {
16    pub(crate) fn parse(args: IdleArgs, item: ItemFn) -> parse::Result<Self> {
17        let valid_signature = util::check_fn_signature(&item, false)
18            && item.sig.inputs.len() == 1
19            && util::type_is_bottom(&item.sig.output);
20
21        let name = item.sig.ident.to_string();
22
23        if valid_signature {
24            if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
25                if rest.is_empty() {
26                    return Ok(Idle {
27                        args,
28                        attrs: item.attrs,
29                        context,
30                        name: item.sig.ident,
31                        stmts: item.block.stmts,
32                        is_extern: false,
33                    });
34                }
35            }
36        }
37
38        Err(parse::Error::new(
39            item.sig.ident.span(),
40            format!("this `#[idle]` function must have signature `fn({name}::Context) -> !`"),
41        ))
42    }
43
44    pub(crate) fn parse_foreign(args: IdleArgs, item: ForeignItemFn) -> parse::Result<Self> {
45        let valid_signature = util::check_foreign_fn_signature(&item, false)
46            && item.sig.inputs.len() == 1
47            && util::type_is_bottom(&item.sig.output);
48
49        let name = item.sig.ident.to_string();
50
51        if valid_signature {
52            if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
53                if rest.is_empty() {
54                    return Ok(Idle {
55                        args,
56                        attrs: item.attrs,
57                        context,
58                        name: item.sig.ident,
59                        stmts: Vec::<Stmt>::new(),
60                        is_extern: true,
61                    });
62                }
63            }
64        }
65
66        Err(parse::Error::new(
67            item.sig.ident.span(),
68            format!("this `#[idle]` function must have signature `fn({name}::Context) -> !`"),
69        ))
70    }
71}