1use crate::{param::Param, serde_state_mutability_compat, utils::*, EventParam, StateMutability};
2use alloc::{borrow::Cow, string::String, vec::Vec};
3use alloy_primitives::{keccak256, Selector, B256};
4use core::str::FromStr;
5use parser::utils::ParsedSignature;
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8macro_rules! abi_items {
10 ($(
11 $(#[$attr:meta])*
12 $vis:vis struct $name:ident : $name_lower:literal {$(
13 $(#[$fattr:meta])*
14 $fvis:vis $field:ident : $type:ty,
15 )*}
16 )*) => {
17 $(
18 $(#[$attr])*
19 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
20 #[serde(rename = $name_lower, rename_all = "camelCase", tag = "type")]
21 $vis struct $name {$(
22 $(#[$fattr])*
23 $fvis $field: $type,
24 )*}
25
26 impl From<$name> for AbiItem<'_> {
27 #[inline]
28 fn from(item: $name) -> Self {
29 AbiItem::$name(Cow::Owned(item))
30 }
31 }
32
33 impl<'a> From<&'a $name> for AbiItem<'a> {
34 #[inline]
35 fn from(item: &'a $name) -> Self {
36 AbiItem::$name(Cow::Borrowed(item))
37 }
38 }
39 )*
40
41 #[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)]
48 #[serde(tag = "type", rename_all = "camelCase")]
49 pub enum AbiItem<'a> {$(
50 #[doc = concat!("A JSON ABI [`", stringify!($name), "`].")]
51 $name(Cow<'a, $name>),
52 )*}
53
54 impl Serialize for AbiItem<'_> {
55 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
56 match self {$(
57 Self::$name(item) => item.serialize(serializer),
58 )*}
59 }
60 }
61
62 impl AbiItem<'_> {
63 #[inline]
74 pub const fn json_type(&self) -> &'static str {
75 match self {$(
76 Self::$name(_) => $name_lower,
77 )*}
78 }
79 }
80 };
81}
82
83abi_items! {
84 pub struct Constructor: "constructor" {
86 pub inputs: Vec<Param>,
88 #[serde(default, flatten, with = "serde_state_mutability_compat")]
90 pub state_mutability: StateMutability,
91 }
92
93 #[derive(Copy)]
95 pub struct Fallback: "fallback" {
96 #[serde(default, flatten, with = "serde_state_mutability_compat")]
98 pub state_mutability: StateMutability,
99 }
100
101 #[derive(Copy)]
103 pub struct Receive: "receive" {
104 #[serde(default, flatten, with = "serde_state_mutability_compat")]
106 pub state_mutability: StateMutability,
107 }
108
109 pub struct Function: "function" {
111 #[serde(deserialize_with = "validated_identifier")]
113 pub name: String,
114 pub inputs: Vec<Param>,
116 pub outputs: Vec<Param>,
118 #[serde(default, flatten, with = "serde_state_mutability_compat")]
120 pub state_mutability: StateMutability,
121 }
122
123 pub struct Event: "event" {
125 #[serde(deserialize_with = "validated_identifier")]
127 pub name: String,
128 pub inputs: Vec<EventParam>,
130 pub anonymous: bool,
134 }
135
136 pub struct Error: "error" {
138 #[serde(deserialize_with = "validated_identifier")]
140 pub name: String,
141 pub inputs: Vec<Param>,
143 }
144}
145
146#[inline]
147fn validated_identifier<'de, D: Deserializer<'de>>(deserializer: D) -> Result<String, D::Error> {
148 let s = String::deserialize(deserializer)?;
149 validate_identifier(&s)?;
150 Ok(s)
151}
152
153impl FromStr for AbiItem<'_> {
154 type Err = parser::Error;
155
156 #[inline]
157 fn from_str(s: &str) -> Result<Self, Self::Err> {
158 Self::parse(s)
159 }
160}
161
162impl AbiItem<'_> {
163 pub fn parse(mut input: &str) -> parser::Result<Self> {
177 let copy = input;
179 match parser::utils::parse_item_keyword(&mut input)? {
180 "constructor" => Constructor::parse(copy).map(Into::into),
181 "function" => Function::parse(input).map(Into::into),
182 "error" => Error::parse(input).map(Into::into),
183 "event" => Event::parse(input).map(Into::into),
184 keyword => Err(parser::Error::new(format_args!(
185 "invalid AbiItem keyword: {keyword:?}, \
186 expected one of \"constructor\", \"function\", \"error\", or \"event\""
187 ))),
188 }
189 }
190
191 #[inline]
193 pub const fn debug_name(&self) -> &'static str {
194 match self {
195 AbiItem::Constructor(_) => "Constructor",
196 AbiItem::Fallback(_) => "Fallback",
197 AbiItem::Receive(_) => "Receive",
198 AbiItem::Function(_) => "Function",
199 AbiItem::Event(_) => "Event",
200 AbiItem::Error(_) => "Error",
201 }
202 }
203
204 #[inline]
206 pub fn name(&self) -> Option<&String> {
207 match self {
208 Self::Event(item) => Some(&item.name),
209 Self::Error(item) => Some(&item.name),
210 Self::Function(item) => Some(&item.name),
211 Self::Constructor(_) | Self::Fallback(_) | Self::Receive(_) => None,
212 }
213 }
214
215 #[inline]
219 pub fn name_mut(&mut self) -> Option<&mut String> {
220 match self {
221 Self::Event(item) => Some(&mut item.to_mut().name),
222 Self::Error(item) => Some(&mut item.to_mut().name),
223 Self::Function(item) => Some(&mut item.to_mut().name),
224 Self::Constructor(_) | Self::Fallback(_) | Self::Receive(_) => None,
225 }
226 }
227
228 #[inline]
230 pub fn state_mutability(&self) -> Option<StateMutability> {
231 match self {
232 Self::Constructor(item) => Some(item.state_mutability),
233 Self::Fallback(item) => Some(item.state_mutability),
234 Self::Receive(item) => Some(item.state_mutability),
235 Self::Function(item) => Some(item.state_mutability),
236 Self::Event(_) | Self::Error(_) => None,
237 }
238 }
239
240 #[inline]
244 pub fn state_mutability_mut(&mut self) -> Option<&mut StateMutability> {
245 match self {
246 Self::Constructor(item) => Some(&mut item.to_mut().state_mutability),
247 Self::Fallback(item) => Some(&mut item.to_mut().state_mutability),
248 Self::Receive(item) => Some(&mut item.to_mut().state_mutability),
249 Self::Function(item) => Some(&mut item.to_mut().state_mutability),
250 Self::Event(_) | Self::Error(_) => None,
251 }
252 }
253
254 #[inline]
258 pub fn inputs(&self) -> Option<&Vec<Param>> {
259 match self {
260 Self::Error(item) => Some(&item.inputs),
261 Self::Constructor(item) => Some(&item.inputs),
262 Self::Function(item) => Some(&item.inputs),
263 Self::Event(_) | Self::Fallback(_) | Self::Receive(_) => None,
264 }
265 }
266
267 #[inline]
273 pub fn inputs_mut(&mut self) -> Option<&mut Vec<Param>> {
274 match self {
275 Self::Error(item) => Some(&mut item.to_mut().inputs),
276 Self::Constructor(item) => Some(&mut item.to_mut().inputs),
277 Self::Function(item) => Some(&mut item.to_mut().inputs),
278 Self::Event(_) | Self::Fallback(_) | Self::Receive(_) => None,
279 }
280 }
281
282 #[inline]
286 pub fn event_inputs(&self) -> Option<&Vec<EventParam>> {
287 match self {
288 Self::Event(item) => Some(&item.inputs),
289 Self::Constructor(_)
290 | Self::Fallback(_)
291 | Self::Receive(_)
292 | Self::Error(_)
293 | Self::Function(_) => None,
294 }
295 }
296
297 #[inline]
303 pub fn event_inputs_mut(&mut self) -> Option<&mut Vec<EventParam>> {
304 match self {
305 Self::Event(item) => Some(&mut item.to_mut().inputs),
306 Self::Constructor(_)
307 | Self::Fallback(_)
308 | Self::Receive(_)
309 | Self::Error(_)
310 | Self::Function(_) => None,
311 }
312 }
313
314 #[inline]
316 pub fn outputs(&self) -> Option<&Vec<Param>> {
317 match self {
318 Self::Function(item) => Some(&item.outputs),
319 Self::Constructor(_)
320 | Self::Fallback(_)
321 | Self::Receive(_)
322 | Self::Error(_)
323 | Self::Event(_) => None,
324 }
325 }
326
327 #[inline]
329 pub fn outputs_mut(&mut self) -> Option<&mut Vec<Param>> {
330 match self {
331 Self::Function(item) => Some(&mut item.to_mut().outputs),
332 Self::Constructor(_)
333 | Self::Fallback(_)
334 | Self::Receive(_)
335 | Self::Error(_)
336 | Self::Event(_) => None,
337 }
338 }
339}
340
341impl FromStr for Constructor {
342 type Err = parser::Error;
343
344 #[inline]
345 fn from_str(s: &str) -> Result<Self, Self::Err> {
346 Self::parse(s)
347 }
348}
349
350impl Constructor {
351 #[inline]
371 pub fn parse(s: &str) -> parser::Result<Self> {
372 parse_sig::<false>(s).and_then(Self::parsed)
373 }
374
375 fn parsed(sig: ParsedSignature<Param>) -> parser::Result<Self> {
376 let ParsedSignature { name, inputs, outputs, anonymous, state_mutability } = sig;
377 if name != "constructor" {
378 return Err(parser::Error::new("constructors' name must be exactly \"constructor\""));
379 }
380 if !outputs.is_empty() {
381 return Err(parser::Error::new("constructors cannot have outputs"));
382 }
383 if anonymous {
384 return Err(parser::Error::new("constructors cannot be anonymous"));
385 }
386 Ok(Self { inputs, state_mutability: state_mutability.unwrap_or_default() })
387 }
388}
389
390impl FromStr for Error {
391 type Err = parser::Error;
392
393 #[inline]
394 fn from_str(s: &str) -> Result<Self, Self::Err> {
395 Self::parse(s)
396 }
397}
398
399impl Error {
400 #[inline]
418 pub fn parse(s: &str) -> parser::Result<Self> {
419 parse_maybe_prefixed(s, "error", parse_sig::<false>).and_then(Self::parsed)
420 }
421
422 fn parsed(sig: ParsedSignature<Param>) -> parser::Result<Self> {
423 let ParsedSignature { name, inputs, outputs, anonymous, state_mutability } = sig;
424 if !outputs.is_empty() {
425 return Err(parser::Error::new("errors cannot have outputs"));
426 }
427 if anonymous {
428 return Err(parser::Error::new("errors cannot be anonymous"));
429 }
430 if state_mutability.is_some() {
431 return Err(parser::Error::new("errors cannot have mutability"));
432 }
433 Ok(Self { name, inputs })
434 }
435
436 #[inline]
440 pub fn signature(&self) -> String {
441 signature(&self.name, &self.inputs, None)
442 }
443
444 #[inline]
446 pub fn selector(&self) -> Selector {
447 selector(&self.signature())
448 }
449}
450
451impl FromStr for Function {
452 type Err = parser::Error;
453
454 #[inline]
455 fn from_str(s: &str) -> Result<Self, Self::Err> {
456 Self::parse(s)
457 }
458}
459
460impl Function {
461 #[inline]
503 pub fn parse(s: &str) -> parser::Result<Self> {
504 parse_maybe_prefixed(s, "function", parse_sig::<true>).and_then(Self::parsed)
505 }
506
507 fn parsed(sig: ParsedSignature<Param>) -> parser::Result<Self> {
508 let ParsedSignature { name, inputs, outputs, anonymous, state_mutability } = sig;
509 if anonymous {
510 return Err(parser::Error::new("functions cannot be anonymous"));
511 }
512 Ok(Self { name, inputs, outputs, state_mutability: state_mutability.unwrap_or_default() })
513 }
514
515 #[inline]
519 pub fn signature(&self) -> String {
520 signature(&self.name, &self.inputs, None)
521 }
522
523 #[inline]
529 pub fn signature_with_outputs(&self) -> String {
530 signature(&self.name, &self.inputs, Some(&self.outputs))
531 }
532
533 #[inline]
540 pub fn full_signature(&self) -> String {
541 full_signature(&self.name, &self.inputs, Some(&self.outputs), self.state_mutability)
542 }
543
544 #[inline]
546 pub fn selector(&self) -> Selector {
547 selector(&self.signature())
548 }
549}
550
551impl FromStr for Event {
552 type Err = parser::Error;
553
554 #[inline]
555 fn from_str(s: &str) -> Result<Self, Self::Err> {
556 Self::parse(s)
557 }
558}
559
560impl Event {
561 #[inline]
584 pub fn parse(s: &str) -> parser::Result<Self> {
585 parse_maybe_prefixed(s, "event", parse_event_sig).and_then(Self::parsed)
586 }
587
588 fn parsed(sig: ParsedSignature<EventParam>) -> parser::Result<Self> {
589 let ParsedSignature { name, inputs, outputs, anonymous, state_mutability } = sig;
590 if !outputs.is_empty() {
591 return Err(parser::Error::new("events cannot have outputs"));
592 }
593 if state_mutability.is_some() {
594 return Err(parser::Error::new("events cannot have state mutability"));
595 }
596 Ok(Self { name, inputs, anonymous })
597 }
598
599 #[inline]
603 pub fn signature(&self) -> String {
604 event_signature(&self.name, &self.inputs)
605 }
606
607 #[inline]
614 pub fn full_signature(&self) -> String {
615 event_full_signature(&self.name, &self.inputs)
616 }
617
618 #[inline]
620 pub fn selector(&self) -> B256 {
621 keccak256(self.signature().as_bytes())
622 }
623
624 #[inline]
626 pub fn num_topics(&self) -> usize {
627 !self.anonymous as usize + self.inputs.iter().filter(|input| input.indexed).count()
628 }
629}
630
631#[cfg(test)]
632mod tests {
633 use super::*;
634
635 fn param2(kind: &str, name: &str) -> Param {
640 Param { ty: kind.into(), name: name.into(), internal_type: None, components: vec![] }
641 }
642
643 #[test]
644 fn parse_prefixes() {
645 for prefix in ["function", "error", "event"] {
646 let name = "foo";
647 let name1 = format!("{prefix} {name}");
648 let name2 = format!("{prefix}{name}");
649 assert_eq!(AbiItem::parse(&format!("{name1}()")).unwrap().name().unwrap(), name);
650 assert!(AbiItem::parse(&format!("{name2}()")).is_err());
651 }
652 }
653
654 #[test]
655 fn parse_function_prefix() {
656 let new = |name: &str| Function {
657 name: name.into(),
658 inputs: vec![],
659 outputs: vec![],
660 state_mutability: StateMutability::NonPayable,
661 };
662 assert_eq!(Function::parse("foo()"), Ok(new("foo")));
663 assert_eq!(Function::parse("function foo()"), Ok(new("foo")));
664 assert_eq!(Function::parse("functionfoo()"), Ok(new("functionfoo")));
665 assert_eq!(Function::parse("function functionfoo()"), Ok(new("functionfoo")));
666 }
667
668 #[test]
669 fn parse_event_prefix() {
670 let new = |name: &str| Event { name: name.into(), inputs: vec![], anonymous: false };
671 assert_eq!(Event::parse("foo()"), Ok(new("foo")));
672 assert_eq!(Event::parse("event foo()"), Ok(new("foo")));
673 assert_eq!(Event::parse("eventfoo()"), Ok(new("eventfoo")));
674 assert_eq!(Event::parse("event eventfoo()"), Ok(new("eventfoo")));
675 }
676
677 #[test]
678 fn parse_error_prefix() {
679 let new = |name: &str| Error { name: name.into(), inputs: vec![] };
680 assert_eq!(Error::parse("foo()"), Ok(new("foo")));
681 assert_eq!(Error::parse("error foo()"), Ok(new("foo")));
682 assert_eq!(Error::parse("errorfoo()"), Ok(new("errorfoo")));
683 assert_eq!(Error::parse("error errorfoo()"), Ok(new("errorfoo")));
684 }
685
686 #[test]
687 fn parse_full() {
688 assert_eq!(
690 Function::parse("function foo(uint256 a, uint256 b) external returns (uint256)"),
691 Ok(Function {
692 name: "foo".into(),
693 inputs: vec![param2("uint256", "a"), param2("uint256", "b")],
694 outputs: vec![param2("uint256", "")],
695 state_mutability: StateMutability::NonPayable,
696 })
697 );
698
699 assert_eq!(
701 Function::parse("function balanceOf(address owner) view returns (uint256 balance)"),
702 Ok(Function {
703 name: "balanceOf".into(),
704 inputs: vec![param2("address", "owner")],
705 outputs: vec![param2("uint256", "balance")],
706 state_mutability: StateMutability::View,
707 })
708 );
709 }
710
711 #[test]
713 fn parse_stack_overflow() {
714 let s = "error J((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((";
715 AbiItem::parse(s).unwrap_err();
716 }
717}