rtic_syntax/parse/
hardware_task.rs

1use syn::{parse, ForeignItemFn, ItemFn, Stmt};
2
3use crate::parse::util::FilterAttrs;
4use crate::{
5    ast::{HardwareTask, HardwareTaskArgs},
6    parse::util,
7};
8
9impl HardwareTask {
10    pub(crate) fn parse(args: HardwareTaskArgs, item: ItemFn) -> parse::Result<Self> {
11        let span = item.sig.ident.span();
12        let valid_signature = util::check_fn_signature(&item)
13            && item.sig.inputs.len() == 1
14            && util::type_is_unit(&item.sig.output);
15
16        let name = item.sig.ident.to_string();
17
18        if name == "init" || name == "idle" {
19            return Err(parse::Error::new(
20                span,
21                "tasks cannot be named `init` or `idle`",
22            ));
23        }
24
25        if valid_signature {
26            if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
27                if rest.is_empty() {
28                    let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
29
30                    return Ok(HardwareTask {
31                        args,
32                        cfgs,
33                        attrs,
34                        context,
35                        stmts: item.block.stmts,
36                        is_extern: false,
37                    });
38                }
39            }
40        }
41
42        Err(parse::Error::new(
43            span,
44            format!(
45                "this task handler must have type signature `fn({}::Context)`",
46                name
47            ),
48        ))
49    }
50}
51
52impl HardwareTask {
53    pub(crate) fn parse_foreign(
54        args: HardwareTaskArgs,
55        item: ForeignItemFn,
56    ) -> parse::Result<Self> {
57        let span = item.sig.ident.span();
58        let valid_signature = util::check_foreign_fn_signature(&item)
59            && item.sig.inputs.len() == 1
60            && util::type_is_unit(&item.sig.output);
61
62        let name = item.sig.ident.to_string();
63
64        if name == "init" || name == "idle" {
65            return Err(parse::Error::new(
66                span,
67                "tasks cannot be named `init` or `idle`",
68            ));
69        }
70
71        if valid_signature {
72            if let Some((context, Ok(rest))) = util::parse_inputs(item.sig.inputs, &name) {
73                if rest.is_empty() {
74                    let FilterAttrs { cfgs, attrs, .. } = util::filter_attributes(item.attrs);
75
76                    return Ok(HardwareTask {
77                        args,
78                        cfgs,
79                        attrs,
80                        context,
81                        stmts: Vec::<Stmt>::new(),
82                        is_extern: true,
83                    });
84                }
85            }
86        }
87
88        Err(parse::Error::new(
89            span,
90            format!(
91                "this task handler must have type signature `fn({}::Context)`",
92                name
93            ),
94        ))
95    }
96}