rtic_macros/syntax/parse/
software_task.rs

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