dharitri_sc_derive/parse/attributes/
payable_attr.rs1use crate::parse::attributes::util::{clean_string, is_first_char_numeric};
2
3use super::attr_names::*;
4
5pub struct PayableAttribute {
6 pub identifier: String,
7}
8
9impl PayableAttribute {
10 pub fn parse(attr: &syn::Attribute) -> Option<PayableAttribute> {
11 if let Some(first_seg) = attr.path().segments.first() {
12 if first_seg.ident == ATTR_PAYABLE {
13 Some(PayableAttribute {
14 identifier: extract_token_identifier(attr),
15 })
16 } else {
17 None
18 }
19 } else {
20 None
21 }
22 }
23}
24
25fn extract_token_identifier(attr: &syn::Attribute) -> String {
28 match attr.meta.clone() {
29 syn::Meta::Path(_) => {
30 "*".to_owned()
32 },
33 syn::Meta::List(list) => {
34 let mut iter = list.tokens.into_iter();
35 let ticker = match iter.next() {
36 Some(proc_macro2::TokenTree::Literal(literal)) => {
37 let clean = clean_string(literal.to_string());
38 assert!(
39 !clean.is_empty(),
40 "ticker can not be empty. attribute needs 1 string argument: Replace with #[payable(\"*\")] or #[payable(\"REWA\")"
41 );
42
43 assert!(!is_first_char_numeric(&clean), "argument can not be a number");
44
45 if clean
46 .chars()
47 .next()
48 .is_some_and(|s|
49 s == '*'
50 ) {
51 assert!(clean.len() == 1usize, "attribute needs 1 string argument: \"*\", \"REWA\" or token identifier");
52 }
53
54 clean
55 },
56 Some(_) => panic!("expected a string as argument"),
57 None => panic!("argument can not be empty. attribute needs 1 string argument: Replace with #[payable(\"*\")] or #[payable(\"REWA\")"),
58 };
59
60 assert!(
61 iter.next().is_none(),
62 "too many tokens in attribute argument"
63 );
64 ticker
65 },
66 syn::Meta::NameValue(_) => panic!(
67 "attribute can not be name value. attribute needs 1 string argument: \"*\" or \"REWA\""
68 ),
69 }
70}