ink_ir/ir/event/
signature_topic.rs1use core::fmt::{
16 Display,
17 Formatter,
18};
19
20use impl_serde::serialize as serde_hex;
21use syn::spanned::Spanned;
22
23use crate::ast;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct SignatureTopic {
30 topic: [u8; 32],
31}
32
33impl SignatureTopic {
34 pub fn to_bytes(&self) -> [u8; 32] {
36 self.topic
37 }
38
39 pub fn to_hex(&self) -> String {
41 serde_hex::to_hex(self.topic.as_slice(), false)
42 }
43}
44
45impl Display for SignatureTopic {
46 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47 write!(f, "{}", self.to_hex())
48 }
49}
50
51impl From<[u8; 32]> for SignatureTopic {
52 fn from(value: [u8; 32]) -> Self {
53 Self { topic: value }
54 }
55}
56
57impl TryFrom<&str> for SignatureTopic {
58 type Error = String;
59
60 fn try_from(value: &str) -> Result<Self, String> {
61 let bytes: [u8; 32] = serde_hex::from_hex(value)
62 .map_err(|_| "`signature_topic` has invalid hex string".to_string())?
63 .try_into()
64 .map_err(|e: Vec<u8>| {
65 format!(
66 "`signature_topic` is expected to be 32-byte hex string. \
67 Found {} bytes",
68 e.len()
69 )
70 })?;
71
72 Ok(Self { topic: bytes })
73 }
74}
75
76impl TryFrom<&syn::LitStr> for SignatureTopic {
77 type Error = syn::Error;
78
79 fn try_from(lit: &syn::LitStr) -> Result<Self, Self::Error> {
80 Self::try_from(lit.value().as_str())
81 .map_err(|err| syn::Error::new_spanned(lit, err))
82 }
83}
84
85impl TryFrom<&syn::Lit> for SignatureTopic {
86 type Error = syn::Error;
87
88 fn try_from(lit: &syn::Lit) -> Result<Self, Self::Error> {
89 if let syn::Lit::Str(s) = lit {
90 Self::try_from(s)
91 } else {
92 Err(format_err_spanned!(
93 lit,
94 "Expected string literal argument for the `signature_topic`"
95 ))
96 }
97 }
98}
99
100impl TryFrom<&ast::MetaValue> for SignatureTopic {
101 type Error = syn::Error;
102
103 fn try_from(value: &ast::MetaValue) -> Result<Self, Self::Error> {
104 if let ast::MetaValue::Lit(lit) = value {
105 Self::try_from(lit)
106 } else {
107 Err(format_err_spanned!(
108 value,
109 "Expected string argument for the `signature_topic`"
110 ))
111 }
112 }
113}
114
115impl TryFrom<ast::AttributeArgs> for Option<SignatureTopic> {
116 type Error = syn::Error;
117
118 fn try_from(args: ast::AttributeArgs) -> Result<Self, Self::Error> {
119 let mut signature_topic: Option<SignatureTopic> = None;
120 for arg in args.into_iter() {
121 if arg.name().is_ident("signature_topic") {
122 if signature_topic.is_some() {
123 return Err(format_err!(
124 arg.span(),
125 "encountered duplicate ink! event configuration argument"
126 ));
127 }
128 signature_topic =
129 arg.value().map(SignatureTopic::try_from).transpose()?;
130 } else {
131 return Err(format_err_spanned!(
132 arg,
133 "encountered unknown or unsupported ink! event item configuration argument",
134 ));
135 }
136 }
137 Ok(signature_topic)
138 }
139}
140
141impl TryFrom<&syn::MetaNameValue> for SignatureTopic {
142 type Error = syn::Error;
143
144 fn try_from(nv: &syn::MetaNameValue) -> Result<Self, Self::Error> {
145 if nv.path.is_ident("signature_topic") {
146 if let syn::Expr::Lit(lit_expr) = &nv.value {
147 Self::try_from(&lit_expr.lit)
148 } else {
149 Err(format_err_spanned!(&nv.value, "Expected literal argument"))
150 }
151 } else {
152 Err(format_err_spanned!(nv, "Expected `signature_topic` ident"))
153 }
154 }
155}