cffi_impl/attr/
mod.rs

1pub mod invoke;
2pub mod marshal;
3
4use marshal::MarshalAttr;
5
6#[derive(Debug)]
7pub struct Mapping {
8    pub output_type: syn::Type,
9    pub marshaler: Option<MarshalAttr>,
10}
11
12impl Mapping {
13    pub fn self_type(receiver: &syn::Receiver, parent: &syn::Type) -> Result<Mapping, syn::Error> {
14        let syn::Receiver {
15            reference,
16            mutability,
17            ..
18        } = receiver.clone();
19
20        let path = match parent {
21            syn::Type::Path(path) => path,
22            e => return Err(syn::Error::new_spanned(&e, "not a valid self type path")),
23        };
24
25        let output_type = match (reference, mutability) {
26            (None, _) => syn::Type::Path(path.clone()),
27            (Some((and_token, lifetime)), mutability) => syn::Type::Reference(syn::TypeReference {
28                and_token,
29                lifetime,
30                mutability,
31                elem: Box::new(syn::Type::Path(path.clone())),
32            }),
33        };
34
35        Ok(Mapping {
36            output_type,
37            marshaler: MarshalAttr::self_type(),
38        })
39    }
40}
41
42pub(crate) trait AttrExt {
43    fn drain_marshal_attrs(&mut self) -> Result<Option<MarshalAttr>, syn::Error>;
44}
45
46#[inline]
47fn drain_marshal_attrs(attrs: &mut Vec<syn::Attribute>) -> Result<Option<MarshalAttr>, syn::Error> {
48    let mut unhandled_attrs = vec![];
49    std::mem::swap(attrs, &mut unhandled_attrs);
50
51    let idents = unhandled_attrs
52        .into_iter()
53        .filter_map(|item| match MarshalAttr::from_attribute(item.clone()) {
54            Ok(None) => {
55                attrs.push(item);
56                return None;
57            }
58            Ok(Some(v)) => Some(Ok(v)),
59            Err(e) => return Some(Err(e)),
60        })
61        .collect::<Result<Vec<_>, _>>();
62
63    let mut idents = match idents {
64        Ok(v) => v,
65        Err(e) => return Err(e),
66    };
67
68    Ok(idents.pop())
69}
70
71impl AttrExt for syn::PatType {
72    fn drain_marshal_attrs(&mut self) -> Result<Option<MarshalAttr>, syn::Error> {
73        drain_marshal_attrs(&mut self.attrs)
74    }
75}
76
77impl AttrExt for syn::FnArg {
78    fn drain_marshal_attrs(&mut self) -> Result<Option<MarshalAttr>, syn::Error> {
79        match self {
80            syn::FnArg::Receiver(receiver) => drain_marshal_attrs(&mut receiver.attrs),
81            syn::FnArg::Typed(typed) => drain_marshal_attrs(&mut typed.attrs),
82        }
83    }
84}
85
86pub(crate) trait SignatureExt {
87    fn drain_mappings(
88        &mut self,
89        parent_type: Option<&syn::Type>,
90    ) -> Result<Vec<Mapping>, syn::Error>;
91}
92
93impl SignatureExt for syn::Signature {
94    fn drain_mappings(
95        &mut self,
96        parent_type: Option<&syn::Type>,
97    ) -> Result<Vec<Mapping>, syn::Error> {
98        self.inputs
99            .iter_mut()
100            .filter_map(|mut input| {
101                // Check if we're a self-type, and short-circuit
102                // TODO: this should use marshal_attr like normal typed fields
103                let input = match &mut input {
104                    syn::FnArg::Receiver(receiver) => {
105                        if let Some(parent_type) = parent_type {
106                            return Some(Mapping::self_type(receiver, parent_type));
107                        } else {
108                            return Some(Err(syn::Error::new_spanned(
109                                &receiver,
110                                "no self type found; using invoke wrong?",
111                            )));
112                        }
113                    }
114                    syn::FnArg::Typed(t) => t,
115                };
116
117                let marshaler = match input.drain_marshal_attrs() {
118                    Ok(v) => v.or_else(|| MarshalAttr::from_defaults_by_type(&input.ty)),
119                    Err(e) => return Some(Err(e)),
120                };
121
122                Some(Ok(Mapping {
123                    output_type: *input.ty.clone(),
124                    marshaler,
125                }))
126            })
127            .collect::<Result<Vec<_>, _>>()
128    }
129}