fp_bindgen/
functions.rs

1use crate::utils::normalize_return_type;
2use crate::{docs::get_doc_lines, types::TypeIdent};
3use quote::ToTokens;
4use std::{collections::BTreeSet, convert::TryFrom};
5use syn::{FnArg, ForeignItemFn};
6
7/// Maps from function name to the stringified function declaration.
8#[derive(Debug, Default)]
9pub struct FunctionList(BTreeSet<Function>);
10
11impl FunctionList {
12    pub fn add_function(&mut self, function_decl: &str) {
13        self.0.insert(Function::new(function_decl));
14    }
15
16    pub fn iter(&self) -> std::collections::btree_set::Iter<'_, Function> {
17        self.0.iter()
18    }
19
20    pub fn new() -> Self {
21        Self(BTreeSet::new())
22    }
23}
24
25impl IntoIterator for FunctionList {
26    type Item = Function;
27    type IntoIter = std::collections::btree_set::IntoIter<Function>;
28
29    fn into_iter(self) -> Self::IntoIter {
30        self.0.into_iter()
31    }
32}
33
34impl<'a> IntoIterator for &'a FunctionList {
35    type Item = &'a Function;
36    type IntoIter = std::collections::btree_set::Iter<'a, Function>;
37
38    fn into_iter(self) -> Self::IntoIter {
39        self.0.iter()
40    }
41}
42
43#[derive(Debug, Eq, PartialEq)]
44pub struct Function {
45    pub name: String,
46    pub doc_lines: Vec<String>,
47    pub args: Vec<FunctionArg>,
48    pub return_type: Option<TypeIdent>,
49    pub is_async: bool,
50}
51
52impl Function {
53    pub fn new(decl: &str) -> Self {
54        let item =
55            syn::parse_str::<ForeignItemFn>(decl).expect("Cannot parse function declaration");
56
57        let name = item.sig.ident.to_string();
58        let doc_lines = get_doc_lines(&item.attrs);
59        let args = item
60            .sig
61            .inputs
62            .iter()
63            .map(|input| match input {
64                FnArg::Receiver(_) => panic!(
65                    "Methods are not supported. Found `self` in function declaration: {:?}",
66                    item
67                ),
68                FnArg::Typed(arg) => FunctionArg {
69                    name: arg.pat.to_token_stream().to_string(),
70                    ty: TypeIdent::try_from(arg.ty.as_ref()).unwrap_or_else(|e| {
71                        panic!("Invalid argument type for function {}: {}", name, e)
72                    }),
73                },
74            })
75            .collect();
76        let return_type = normalize_return_type(&item.sig.output).map(|return_type| {
77            TypeIdent::try_from(return_type)
78                .unwrap_or_else(|_| panic!("Invalid return type for function {}", name))
79        });
80        let is_async = item.sig.asyncness.is_some();
81
82        Self {
83            name,
84            doc_lines,
85            args,
86            return_type,
87            is_async,
88        }
89    }
90}
91
92impl Ord for Function {
93    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
94        self.name.cmp(&other.name)
95    }
96}
97
98impl PartialOrd for Function {
99    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
100        self.name.partial_cmp(&other.name)
101    }
102}
103
104#[derive(Debug, Eq, PartialEq)]
105pub struct FunctionArg {
106    pub name: String,
107    pub ty: TypeIdent,
108}