ink_ir/ir/trait_def/
config.rs

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.
14
15use crate::{
16    ast,
17    utils::{
18        duplicate_config_err,
19        WhitelistedAttributes,
20    },
21};
22
23/// 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.
33    namespace: Option<syn::LitStr>,
34    /// The set of attributes that can be passed to call builder and forwarder in the
35    /// codegen.
36    whitelisted_attributes: WhitelistedAttributes,
37}
38
39impl 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)]
46    pub fn with_namespace(mut self, namespace: &str) -> Self {
47        self.namespace =
48            Some(syn::LitStr::new(namespace, proc_macro2::Span::call_site()));
49        self
50    }
51}
52
53impl TryFrom<ast::AttributeArgs> for TraitDefinitionConfig {
54    type Error = syn::Error;
55
56    fn try_from(args: ast::AttributeArgs) -> Result<Self, Self::Error> {
57        let mut namespace: Option<(syn::LitStr, ast::MetaNameValue)> = None;
58        let mut whitelisted_attributes = WhitelistedAttributes::default();
59        for arg in args.into_iter() {
60            if arg.name().is_ident("namespace") {
61                if let Some((_, meta_name_value)) = namespace {
62                    return Err(duplicate_config_err(
63                        meta_name_value,
64                        arg,
65                        "namespace",
66                        "trait definition",
67                    ));
68                }
69                let namespace_info = arg
70                    .name_value()
71                    .zip(arg.value().and_then(ast::MetaValue::as_lit_string));
72                if let Some((name_value, lit_str)) = namespace_info {
73                    if syn::parse_str::<syn::Ident>(&lit_str.value()).is_err() {
74                        return 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 {
81                    return 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") {
87                if let Some(name_value) = arg.name_value() {
88                    whitelisted_attributes.parse_arg_value(name_value)?;
89                } else {
90                    return Err(format_err_spanned!(
91                        arg,
92                        "expected a string literal value for `keep_attr` ink! configuration argument",
93                    ));
94                }
95            } else {
96                return Err(format_err_spanned!(
97                    arg,
98                    "encountered unknown or unsupported ink! trait definition configuration argument",
99                ));
100            }
101        }
102        Ok(TraitDefinitionConfig {
103            namespace: namespace.map(|(value, _)| value),
104            whitelisted_attributes,
105        })
106    }
107}
108
109impl TraitDefinitionConfig {
110    /// Returns the namespace configuration argument if any as string.
111    pub fn namespace(&self) -> Option<&syn::LitStr> {
112        self.namespace.as_ref()
113    }
114
115    /// Returns the set of attributes that can be passed to call builder and
116    /// forwarder in the codegen.
117    pub fn whitelisted_attributes(&self) -> &WhitelistedAttributes {
118        &self.whitelisted_attributes
119    }
120}