sylvia_derive/parser/
variant_descs.rs

1use crate::parser::attributes::VariantAttrForwarding;
2use crate::parser::{MsgAttr, ParsedSylviaAttributes};
3use syn::{Attribute, ImplItem, ItemImpl, ItemTrait, Signature, TraitItem};
4
5/// Type wrapping common data between [ItemImpl] and [ItemTrait].
6pub struct VariantDesc<'a> {
7    msg_attr: Option<MsgAttr>,
8    attrs_to_forward: Vec<VariantAttrForwarding>,
9    sig: &'a Signature,
10}
11
12impl<'a> VariantDesc<'a> {
13    pub fn new(attrs: &'a [Attribute], sig: &'a Signature) -> Self {
14        let sylvia_params = ParsedSylviaAttributes::new(attrs.iter());
15        let attrs_to_forward = sylvia_params.variant_attrs_forward;
16        let msg_attr = sylvia_params.msg_attr;
17        Self {
18            msg_attr,
19            attrs_to_forward,
20            sig,
21        }
22    }
23
24    pub fn into_sig(self) -> &'a Signature {
25        self.sig
26    }
27
28    pub fn attr_msg(&self) -> Option<MsgAttr> {
29        self.msg_attr.clone()
30    }
31
32    pub fn attrs_to_forward(&self) -> Vec<VariantAttrForwarding> {
33        self.attrs_to_forward.clone()
34    }
35}
36
37pub type VariantDescs<'a> = Box<dyn Iterator<Item = VariantDesc<'a>> + 'a>;
38
39/// Trait for extracting attributes and signature of the methods from `ItemImpl` and `ItemTrait`
40/// In most cases these two parameters are being used for preprocessing
41/// so to unify the logic we can use this trait
42pub trait AsVariantDescs {
43    type Iter<'a>: Iterator<Item = VariantDesc<'a>>
44    where
45        Self: 'a;
46
47    fn as_variants(&self) -> Self::Iter<'_>;
48}
49
50impl AsVariantDescs for ItemImpl {
51    type Iter<'a> = VariantDescs<'a>;
52
53    fn as_variants(&self) -> Self::Iter<'_> {
54        Box::new(self.items.iter().filter_map(|item| match item {
55            ImplItem::Fn(method) => Some(VariantDesc::new(&method.attrs, &method.sig)),
56            _ => None,
57        }))
58    }
59}
60
61impl AsVariantDescs for ItemTrait {
62    type Iter<'a> = VariantDescs<'a>;
63
64    fn as_variants(&self) -> Self::Iter<'_> {
65        Box::new(self.items.iter().filter_map(|item| match item {
66            TraitItem::Fn(method) => Some(VariantDesc::new(&method.attrs, &method.sig)),
67            _ => None,
68        }))
69    }
70}