ink_ir/ir/event/
config.rs1use syn::spanned::Spanned;
16
17use super::SignatureTopic;
18use crate::{
19 ast,
20 utils::{
21 duplicate_config_err,
22 extract_name_override,
23 },
24};
25
26#[derive(Debug, PartialEq, Eq)]
28pub struct EventConfig {
29 anonymous: bool,
33 signature_topic: Option<SignatureTopic>,
35 name: Option<String>,
42}
43
44impl EventConfig {
45 pub fn parse<I>(args: I) -> Result<Self, syn::Error>
47 where
48 I: Iterator<Item = ast::Meta>,
49 {
50 let mut anonymous: Option<syn::Path> = None;
51 let mut signature_topic: Option<syn::LitStr> = None;
52 let mut name: Option<syn::LitStr> = None;
53 for arg in args {
54 if arg.name().is_ident("anonymous") {
55 if let Some(lit_bool) = anonymous {
56 return Err(duplicate_config_err(lit_bool, arg, "anonymous", "event"));
57 }
58 if let ast::Meta::Path(path) = arg {
59 anonymous = Some(path)
60 } else {
61 return Err(format_err_spanned!(
62 arg,
63 "encountered an unexpected value for `anonymous` ink! event item configuration argument. \
64 Did you mean #[ink::event(anonymous)] ?",
65 ));
66 }
67 } else if arg.name().is_ident("signature_topic") {
68 if anonymous.is_some() {
69 return Err(format_err_spanned!(
70 arg,
71 "cannot specify `signature_topic` with `anonymous` in ink! event item configuration argument",
72 ));
73 }
74
75 if let Some(lit_str) = signature_topic {
76 return Err(duplicate_config_err(
77 lit_str,
78 arg,
79 "signature_topic",
80 "event",
81 ));
82 }
83 if let Some(lit_str) = arg.value().and_then(ast::MetaValue::as_lit_string)
84 {
85 signature_topic = Some(lit_str.clone())
86 } else {
87 return Err(format_err_spanned!(
88 arg,
89 "expected a string literal value for `signature_topic` ink! event item configuration argument",
90 ));
91 }
92 } else if arg.name().is_ident("name") {
93 if let Some(lit_str) = name {
94 return Err(duplicate_config_err(lit_str, arg, "name", "event"));
95 }
96
97 if let Some(value) = arg.value() {
98 name = Some(extract_name_override(value, arg.span())?);
99 } else {
100 return Err(format_err_spanned!(
101 arg,
102 "expected a string literal value for `name` attribute argument"
103 ));
104 }
105 } else {
106 return Err(format_err_spanned!(
107 arg,
108 "encountered unknown or unsupported ink! event item configuration argument",
109 ));
110 }
111 }
112
113 Ok(EventConfig::new(
114 anonymous.is_some(),
115 signature_topic
116 .as_ref()
117 .map(SignatureTopic::try_from)
118 .transpose()?,
119 name.map(|lit_str| lit_str.value()),
120 ))
121 }
122}
123
124impl TryFrom<ast::AttributeArgs> for EventConfig {
125 type Error = syn::Error;
126
127 fn try_from(args: ast::AttributeArgs) -> Result<Self, Self::Error> {
128 Self::parse(args.into_iter())
129 }
130}
131
132impl TryFrom<&[syn::Attribute]> for EventConfig {
133 type Error = syn::Error;
134
135 fn try_from(attrs: &[syn::Attribute]) -> Result<Self, Self::Error> {
136 let mut ink_attrs = Vec::new();
137 for attr in attrs {
138 if !attr.path().is_ident("ink") {
139 continue;
140 }
141 let nested = attr.parse_args_with(
142 syn::punctuated::Punctuated::<ast::Meta, syn::Token![,]>::parse_separated_nonempty,
143 )?;
144 ink_attrs.extend(nested);
145 }
146 Self::parse(ink_attrs.into_iter())
147 }
148}
149
150impl EventConfig {
151 pub fn new(
153 anonymous: bool,
154 signature_topic: Option<SignatureTopic>,
155 name: Option<String>,
156 ) -> Self {
157 Self {
158 anonymous,
159 signature_topic,
160 name,
161 }
162 }
163
164 pub fn anonymous(&self) -> bool {
166 self.anonymous
167 }
168
169 pub fn signature_topic(&self) -> Option<SignatureTopic> {
171 self.signature_topic
172 }
173
174 pub fn name(&self) -> Option<&str> {
176 self.name.as_deref()
177 }
178}