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
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!(
93 arg.span(),
94 "wildcard selectors are only supported for inherent ink! messages or constructors, not for traits."
95 )))
96 }
97 ir::AttributeArg::Message
98 | ir::AttributeArg::Payable
99 | ir::AttributeArg::Default
100 | ir::AttributeArg::Selector(_) => Ok(()),
101 _ => Err(None),
102 }
103 },
104 )?;
105 Ok((ink_attrs, non_ink_attrs))
106 }
107
108 pub fn attrs(&self) -> Vec<syn::Attribute> {
110 let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs)
111 .expect(Self::INVALID_ATTRIBUTES_ERRSTR);
112 rust_attrs
113 }
114
115 pub fn get_cfg_attrs(&self, span: Span) -> Vec<TokenStream> {
117 extract_cfg_attributes(&self.attrs(), span)
118 }
119
120 pub fn ink_attrs(&self) -> InkAttribute {
122 let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs)
123 .expect(Self::INVALID_ATTRIBUTES_ERRSTR);
124 ink_attrs
125 }
126
127 pub fn sig(&self) -> &syn::Signature {
129 &self.item.sig
130 }
131
132 pub fn receiver(&self) -> Receiver {
136 match self.item.sig.inputs.iter().next() {
137 Some(syn::FnArg::Receiver(receiver)) => {
138 debug_assert!(receiver.reference.is_some());
139 if receiver.mutability.is_some() {
140 Receiver::RefMut
141 } else {
142 Receiver::Ref
143 }
144 }
145 _ => unreachable!("encountered invalid receiver argument for ink! message"),
146 }
147 }
148
149 pub fn inputs(&self) -> InputsIter<'_> {
151 InputsIter::from(self)
152 }
153
154 pub fn output(&self) -> Option<&syn::Type> {
156 match &self.item.sig.output {
157 syn::ReturnType::Default => None,
158 syn::ReturnType::Type(_, return_type) => Some(return_type),
159 }
160 }
161
162 pub fn ident(&self) -> &syn::Ident {
164 &self.item.sig.ident
165 }
166
167 pub fn local_id(&self) -> u32 {
175 utils::local_message_id(self.ident())
176 }
177
178 pub fn span(&self) -> Span {
180 self.item.span()
181 }
182
183 pub fn mutates(&self) -> bool {
185 self.sig()
186 .receiver()
187 .map(|receiver| receiver.mutability.is_some())
188 .expect("encountered missing receiver for ink! message")
189 }
190}
191
192impl<'a> From<&'a InkTraitMessage<'a>> for InputsIter<'a> {
193 fn from(message: &'a InkTraitMessage) -> Self {
194 Self::new(&message.item.sig.inputs)
195 }
196}