alloy_dyn_abi/eip712/
parser.rs1use crate::{
6 eip712::resolver::{PropertyDef, TypeDef},
7 Error,
8};
9use alloc::vec::Vec;
10use parser::{Error as TypeParserError, TypeSpecifier};
11
12#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct PropDef<'a> {
16 pub ty: TypeSpecifier<'a>,
18 pub name: &'a str,
20}
21
22impl PropDef<'_> {
23 pub fn to_owned(&self) -> PropertyDef {
25 PropertyDef::new(self.ty.span, self.name).unwrap()
26 }
27}
28
29impl<'a> TryFrom<&'a str> for PropDef<'a> {
30 type Error = Error;
31
32 #[inline]
33 fn try_from(input: &'a str) -> Result<Self, Self::Error> {
34 Self::parse(input)
35 }
36}
37
38impl<'a> PropDef<'a> {
39 pub fn parse(input: &'a str) -> Result<Self, Error> {
41 let (ty, name) =
42 input.rsplit_once(' ').ok_or_else(|| Error::invalid_property_def(input))?;
43 Ok(PropDef { ty: ty.trim().try_into()?, name: name.trim() })
44 }
45}
46
47#[derive(Clone, Debug, PartialEq, Eq)]
51pub struct ComponentType<'a> {
52 pub span: &'a str,
54 pub type_name: &'a str,
56 pub props: Vec<PropDef<'a>>,
58}
59
60impl<'a> TryFrom<&'a str> for ComponentType<'a> {
61 type Error = Error;
62
63 #[inline]
64 fn try_from(input: &'a str) -> Result<Self, Self::Error> {
65 Self::parse(input)
66 }
67}
68
69impl<'a> ComponentType<'a> {
70 pub fn parse(input: &'a str) -> Result<Self, Error> {
72 let (name, props_str) = input
73 .split_once('(')
74 .ok_or_else(|| Error::TypeParser(TypeParserError::invalid_type_string(input)))?;
75
76 let mut props = vec![];
77 let mut depth = 1; let mut last = 0;
79
80 for (i, c) in props_str.chars().enumerate() {
81 match c {
82 '(' => depth += 1,
83 ')' => {
84 depth -= 1;
85 if depth == 0 {
86 let candidate = &props_str[last..i];
87 if !candidate.is_empty() {
88 props.push(candidate.try_into()?);
89 }
90 last = i + 1;
91 break;
92 }
93 }
94 ',' => {
95 if depth == 1 {
96 props.push(props_str[last..i].try_into()?);
97 last = i + 1;
98 }
99 }
100 _ => {}
101 }
102 }
103
104 Ok(Self { span: &input[..last + name.len() + 1], type_name: name, props })
105 }
106
107 pub fn to_owned(&self) -> TypeDef {
109 TypeDef::new(self.type_name, self.props.iter().map(|p| p.to_owned()).collect()).unwrap()
110 }
111}
112
113#[derive(Debug, PartialEq, Eq)]
115pub struct EncodeType<'a> {
116 pub types: Vec<ComponentType<'a>>,
118}
119
120impl<'a> TryFrom<&'a str> for EncodeType<'a> {
121 type Error = Error;
122
123 #[inline]
124 fn try_from(input: &'a str) -> Result<Self, Self::Error> {
125 Self::parse(input)
126 }
127}
128
129impl<'a> EncodeType<'a> {
130 pub fn parse(input: &'a str) -> Result<Self, Error> {
132 let mut types = vec![];
133 let mut remaining = input;
134
135 while let Ok(t) = ComponentType::parse(remaining) {
136 remaining = &remaining[t.span.len()..];
137 types.push(t);
138 }
139
140 Ok(Self { types })
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 const EXAMPLE: &str = "Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)";
149
150 #[test]
151 fn empty_type() {
152 let empty_domain_type =
153 ComponentType { span: "EIP712Domain()", type_name: "EIP712Domain", props: vec![] };
154 assert_eq!(ComponentType::parse("EIP712Domain()"), Ok(empty_domain_type.clone()));
155
156 assert_eq!(
157 EncodeType::try_from("EIP712Domain()"),
158 Ok(EncodeType { types: vec![empty_domain_type] })
159 );
160 }
161
162 #[test]
163 fn test_component_type() {
164 assert_eq!(
165 ComponentType::parse("Transaction(Person from,Person to,Asset tx)"),
166 Ok(ComponentType {
167 span: "Transaction(Person from,Person to,Asset tx)",
168 type_name: "Transaction",
169 props: vec![
170 "Person from".try_into().unwrap(),
171 "Person to".try_into().unwrap(),
172 "Asset tx".try_into().unwrap(),
173 ],
174 })
175 );
176 }
177
178 #[test]
179 fn test_encode_type() {
180 assert_eq!(
181 EncodeType::parse(EXAMPLE),
182 Ok(EncodeType {
183 types: vec![
184 "Transaction(Person from,Person to,Asset tx)".try_into().unwrap(),
185 "Asset(address token,uint256 amount)".try_into().unwrap(),
186 "Person(address wallet,string name)".try_into().unwrap(),
187 ]
188 })
189 );
190 }
191}