ink_ir/ir/trait_def/item/
trait_item.rs1use super::super::InkAttribute;
16use crate::{
17 ir::{
18 self,
19 attrs::SelectorOrWildcard,
20 utils,
21 utils::extract_cfg_attributes,
22 },
23 InputsIter,
24 Receiver,
25};
26use proc_macro2::{
27 Span,
28 TokenStream,
29};
30use syn::{
31 spanned::Spanned as _,
32 Result,
33};
34
35#[derive(Debug, Clone)]
37pub enum InkTraitItem<'a> {
38 Message(InkTraitMessage<'a>),
39}
40
41impl<'a> InkTraitItem<'a> {
42 pub fn ident(&self) -> &syn::Ident {
44 match self {
45 Self::Message(message) => message.ident(),
46 }
47 }
48
49 pub fn ink_attrs(&self) -> InkAttribute {
51 match self {
52 Self::Message(message) => message.ink_attrs(),
53 }
54 }
55
56 pub fn filter_map_message(self) -> Option<InkTraitMessage<'a>> {
58 match self {
59 Self::Message(ink_trait_message) => Some(ink_trait_message),
60 }
61 }
62}
63
64#[derive(Debug, Clone)]
66pub struct InkTraitMessage<'a> {
67 item: &'a syn::TraitItemFn,
68}
69
70impl<'a> InkTraitMessage<'a> {
71 const INVALID_ATTRIBUTES_ERRSTR: &'static str =
73 "encountered invalid attributes for ink! trait message";
74
75 pub(super) fn new(item: &'a syn::TraitItemFn) -> Self {
77 Self { item }
78 }
79
80 pub(super) fn extract_attributes(
82 span: Span,
83 attrs: &[syn::Attribute],
84 ) -> Result<(InkAttribute, Vec<syn::Attribute>)> {
85 let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes(
86 span,
87 attrs.iter().cloned(),
88 &ir::AttributeArgKind::Message,
89 |arg| {
90 match arg.kind() {
91 ir::AttributeArg::Selector(SelectorOrWildcard::Wildcard) =>
92 Err(Some(format_err!(arg.span(), "wildcard selectors are only supported for inherent ink! messages or constructors, not for traits."))),
93 ir::AttributeArg::Message
94 | ir::AttributeArg::Payable
95 | ir::AttributeArg::Default
96 | ir::AttributeArg::Selector(_) => Ok(()),
97 _ => Err(None),
98 }
99 },
100 )?;
101 Ok((ink_attrs, non_ink_attrs))
102 }
103
104 pub fn attrs(&self) -> Vec<syn::Attribute> {
106 let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs)
107 .expect(Self::INVALID_ATTRIBUTES_ERRSTR);
108 rust_attrs
109 }
110
111 pub fn get_cfg_attrs(&self, span: Span) -> Vec<TokenStream> {
113 extract_cfg_attributes(&self.attrs(), span)
114 }
115
116 pub fn ink_attrs(&self) -> InkAttribute {
118 let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs)
119 .expect(Self::INVALID_ATTRIBUTES_ERRSTR);
120 ink_attrs
121 }
122
123 pub fn sig(&self) -> &syn::Signature {
125 &self.item.sig
126 }
127
128 pub fn receiver(&self) -> Receiver {
132 match self.item.sig.inputs.iter().next() {
133 Some(syn::FnArg::Receiver(receiver)) => {
134 debug_assert!(receiver.reference.is_some());
135 if receiver.mutability.is_some() {
136 Receiver::RefMut
137 } else {
138 Receiver::Ref
139 }
140 }
141 _ => unreachable!("encountered invalid receiver argument for ink! message"),
142 }
143 }
144
145 pub fn inputs(&self) -> InputsIter {
147 InputsIter::from(self)
148 }
149
150 pub fn output(&self) -> Option<&syn::Type> {
152 match &self.item.sig.output {
153 syn::ReturnType::Default => None,
154 syn::ReturnType::Type(_, return_type) => Some(return_type),
155 }
156 }
157
158 pub fn ident(&self) -> &syn::Ident {
160 &self.item.sig.ident
161 }
162
163 pub fn local_id(&self) -> u32 {
171 utils::local_message_id(self.ident())
172 }
173
174 pub fn span(&self) -> Span {
176 self.item.span()
177 }
178
179 pub fn mutates(&self) -> bool {
181 self.sig()
182 .receiver()
183 .map(|receiver| receiver.mutability.is_some())
184 .expect("encountered missing receiver for ink! message")
185 }
186}
187
188impl<'a> From<&'a InkTraitMessage<'a>> for InputsIter<'a> {
189 fn from(message: &'a InkTraitMessage) -> Self {
190 Self::new(&message.item.sig.inputs)
191 }
192}