ink_ir/ir/trait_def/item/
trait_item.rs1use super::super::InkAttribute;
16use crate::{
17 InputsIter,
18 Receiver,
19 ir::{
20 self,
21 attrs::SelectorOrWildcard,
22 utils,
23 utils::extract_cfg_attributes,
24 },
25};
26use proc_macro2::{
27 Span,
28 TokenStream,
29};
30use syn::{
31 Result,
32 spanned::Spanned as _,
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 pub fn name(&self) -> Option<String> {
65 match self {
66 Self::Message(message) => message.name(),
67 }
68 }
69
70 pub fn normalized_name(&self) -> String {
76 match self {
77 Self::Message(message) => message.normalized_name(),
78 }
79 }
80}
81
82#[derive(Debug, Clone)]
84pub struct InkTraitMessage<'a> {
85 item: &'a syn::TraitItemFn,
86}
87
88impl<'a> InkTraitMessage<'a> {
89 const INVALID_ATTRIBUTES_ERRSTR: &'static str =
91 "encountered invalid attributes for ink! trait message";
92
93 pub(super) fn new(item: &'a syn::TraitItemFn) -> Self {
95 Self { item }
96 }
97
98 pub(super) fn extract_attributes(
100 span: Span,
101 attrs: &[syn::Attribute],
102 ) -> Result<(InkAttribute, Vec<syn::Attribute>)> {
103 let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes(
104 span,
105 attrs.iter().cloned(),
106 &ir::AttributeArgKind::Message,
107 |arg| {
108 match arg.kind() {
109 ir::AttributeArg::Selector(SelectorOrWildcard::Wildcard) => {
110 Err(Some(format_err!(
111 arg.span(),
112 "wildcard selectors are only supported for inherent ink! messages or constructors, not for traits."
113 )))
114 }
115 ir::AttributeArg::Message
116 | ir::AttributeArg::Payable
117 | ir::AttributeArg::Default
118 | ir::AttributeArg::Selector(_)
119 | ir::AttributeArg::Name(_) => Ok(()),
120 _ => Err(None),
121 }
122 },
123 )?;
124 Ok((ink_attrs, non_ink_attrs))
125 }
126
127 pub fn attrs(&self) -> Vec<syn::Attribute> {
129 let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs)
130 .expect(Self::INVALID_ATTRIBUTES_ERRSTR);
131 rust_attrs
132 }
133
134 pub fn get_cfg_attrs(&self, span: Span) -> Vec<TokenStream> {
136 extract_cfg_attributes(&self.attrs(), span)
137 }
138
139 pub fn ink_attrs(&self) -> InkAttribute {
141 let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs)
142 .expect(Self::INVALID_ATTRIBUTES_ERRSTR);
143 ink_attrs
144 }
145
146 pub fn sig(&self) -> &syn::Signature {
148 &self.item.sig
149 }
150
151 pub fn receiver(&self) -> Receiver {
155 match self.item.sig.inputs.iter().next() {
156 Some(syn::FnArg::Receiver(receiver)) => {
157 debug_assert!(receiver.reference.is_some());
158 if receiver.mutability.is_some() {
159 Receiver::RefMut
160 } else {
161 Receiver::Ref
162 }
163 }
164 _ => unreachable!("encountered invalid receiver argument for ink! message"),
165 }
166 }
167
168 pub fn inputs(&self) -> InputsIter<'_> {
170 InputsIter::from(self)
171 }
172
173 pub fn output(&self) -> Option<&syn::Type> {
175 match &self.item.sig.output {
176 syn::ReturnType::Default => None,
177 syn::ReturnType::Type(_, return_type) => Some(return_type),
178 }
179 }
180
181 pub fn ident(&self) -> &syn::Ident {
183 &self.item.sig.ident
184 }
185
186 pub fn local_id(&self) -> u32 {
194 utils::local_message_id(&self.normalized_name())
195 }
196
197 pub fn span(&self) -> Span {
199 self.item.span()
200 }
201
202 pub fn mutates(&self) -> bool {
204 self.sig()
205 .receiver()
206 .map(|receiver| receiver.mutability.is_some())
207 .expect("encountered missing receiver for ink! message")
208 }
209
210 pub fn name(&self) -> Option<String> {
212 self.ink_attrs().name()
213 }
214
215 pub fn normalized_name(&self) -> String {
221 self.name().unwrap_or_else(|| self.ident().to_string())
222 }
223}
224
225impl<'a> From<&'a InkTraitMessage<'a>> for InputsIter<'a> {
226 fn from(message: &'a InkTraitMessage) -> Self {
227 Self::new(&message.item.sig.inputs)
228 }
229}