1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
1415use crate::{
16 ast,
17 utils::{
18 duplicate_config_err,
19 WhitelistedAttributes,
20 },
21};
2223/// The ink! configuration.
24#[derive(Debug, Default, PartialEq, Eq)]
25pub struct TraitDefinitionConfig {
26/// Captures the optional custom namespace for the ink! trait definition.
27 ///
28 /// # Note
29 ///
30 /// The namespace configuration parameter is used to influence the generated
31 /// selectors of the ink! trait messages. This is useful to disambiguate
32 /// ink! trait definitions with equal names.
33namespace: Option<syn::LitStr>,
34/// The set of attributes that can be passed to call builder and forwarder in the
35 /// codegen.
36whitelisted_attributes: WhitelistedAttributes,
37}
3839impl TraitDefinitionConfig {
40/// Sets the namespace of the ink! trait definition configuration.
41 ///
42 /// # Note
43 ///
44 /// This is a test-only API.
45#[cfg(test)]
46pub fn with_namespace(mut self, namespace: &str) -> Self {
47self.namespace =
48Some(syn::LitStr::new(namespace, proc_macro2::Span::call_site()));
49self
50}
51}
5253impl TryFrom<ast::AttributeArgs> for TraitDefinitionConfig {
54type Error = syn::Error;
5556fn try_from(args: ast::AttributeArgs) -> Result<Self, Self::Error> {
57let mut namespace: Option<(syn::LitStr, ast::MetaNameValue)> = None;
58let mut whitelisted_attributes = WhitelistedAttributes::default();
59for arg in args.into_iter() {
60if arg.name().is_ident("namespace") {
61if let Some((_, meta_name_value)) = namespace {
62return Err(duplicate_config_err(
63 meta_name_value,
64 arg,
65"namespace",
66"trait definition",
67 ));
68 }
69let namespace_info = arg
70 .name_value()
71 .zip(arg.value().and_then(ast::MetaValue::as_lit_string));
72if let Some((name_value, lit_str)) = namespace_info {
73if syn::parse_str::<syn::Ident>(&lit_str.value()).is_err() {
74return Err(format_err_spanned!(
75 lit_str,
76"encountered invalid Rust identifier for the ink! namespace configuration parameter"
77));
78 }
79 namespace = Some((lit_str.clone(), name_value.clone()))
80 } else {
81return Err(format_err_spanned!(
82 arg,
83"expected a string literal value for `namespace` ink! trait definition configuration argument",
84 ));
85 }
86 } else if arg.name().is_ident("keep_attr") {
87if let Some(name_value) = arg.name_value() {
88 whitelisted_attributes.parse_arg_value(name_value)?;
89 } else {
90return Err(format_err_spanned!(
91 arg,
92"expected a string literal value for `keep_attr` ink! configuration argument",
93 ));
94 }
95 } else {
96return Err(format_err_spanned!(
97 arg,
98"encountered unknown or unsupported ink! trait definition configuration argument",
99 ));
100 }
101 }
102Ok(TraitDefinitionConfig {
103 namespace: namespace.map(|(value, _)| value),
104 whitelisted_attributes,
105 })
106 }
107}
108109impl TraitDefinitionConfig {
110/// Returns the namespace configuration argument if any as string.
111pub fn namespace(&self) -> Option<&syn::LitStr> {
112self.namespace.as_ref()
113 }
114115/// Returns the set of attributes that can be passed to call builder and
116 /// forwarder in the codegen.
117pub fn whitelisted_attributes(&self) -> &WhitelistedAttributes {
118&self.whitelisted_attributes
119 }
120}