1use crate::{
2 internal_type::BorrowedInternalType,
3 utils::{mk_eparam, mk_param, validate_identifier},
4 InternalType,
5};
6use alloc::{borrow::Cow, string::String, vec::Vec};
7use core::{fmt, str::FromStr};
8use parser::{Error, ParameterSpecifier, TypeSpecifier};
9use serde::{de::Unexpected, Deserialize, Deserializer, Serialize, Serializer};
10
11#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
19pub struct Param {
20 #[doc(hidden)]
31 pub ty: String,
32 #[doc(hidden)]
37 pub name: String,
38 pub components: Vec<Param>,
41 pub internal_type: Option<InternalType>,
45}
46
47impl fmt::Display for Param {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 if let Some(it) = &self.internal_type { it.fmt(f) } else { f.write_str(&self.ty) }?;
50 f.write_str(" ")?;
51 f.write_str(&self.name)
52 }
53}
54
55impl<'de> Deserialize<'de> for Param {
56 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
57 ParamInner::deserialize(deserializer).and_then(|inner| {
58 if inner.indexed.is_none() {
59 inner.validate_fields()?;
60 Ok(Self {
61 name: inner.name,
62 ty: inner.ty,
63 internal_type: inner.internal_type,
64 components: inner.components,
65 })
66 } else {
67 Err(serde::de::Error::custom("indexed is not supported in params"))
68 }
69 })
70 }
71}
72
73impl Serialize for Param {
74 #[inline]
75 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
76 self.as_inner().serialize(serializer)
77 }
78}
79
80impl FromStr for Param {
81 type Err = parser::Error;
82
83 #[inline]
84 fn from_str(s: &str) -> Result<Self, Self::Err> {
85 Self::parse(s)
86 }
87}
88
89impl Param {
90 pub fn parse(input: &str) -> parser::Result<Self> {
107 ParameterSpecifier::parse(input).map(|p| mk_param(p.name, p.ty))
108 }
109
110 pub fn new(
112 name: &str,
113 ty: &str,
114 components: Vec<Self>,
115 internal_type: Option<InternalType>,
116 ) -> parser::Result<Self> {
117 Self::validate_fields(name, ty, !components.is_empty())?;
118 Ok(Self { ty: ty.into(), name: name.into(), components, internal_type })
119 }
120
121 #[inline]
124 pub fn name(&self) -> &str {
125 &self.name
126 }
127
128 #[inline]
130 pub const fn internal_type(&self) -> Option<&InternalType> {
131 self.internal_type.as_ref()
132 }
133
134 #[inline]
143 pub fn is_udt(&self) -> bool {
144 match self.internal_type().and_then(|it| it.as_other()) {
145 Some((contract, ty)) => contract.is_some() || (self.is_simple_type() && ty != self.ty),
146 _ => false,
147 }
148 }
149
150 #[inline]
152 pub const fn is_struct(&self) -> bool {
153 match self.internal_type() {
154 Some(ty) => ty.is_struct(),
155 None => false,
156 }
157 }
158
159 #[inline]
161 pub const fn is_enum(&self) -> bool {
162 match self.internal_type() {
163 Some(ty) => ty.is_enum(),
164 None => false,
165 }
166 }
167
168 #[inline]
170 pub const fn is_contract(&self) -> bool {
171 match self.internal_type() {
172 Some(ty) => ty.is_contract(),
173 None => false,
174 }
175 }
176
177 #[inline]
181 pub fn udt_specifier(&self) -> Option<TypeSpecifier<'_>> {
182 if !self.is_udt() {
184 return None;
185 }
186 self.internal_type().and_then(|ty| ty.other_specifier())
187 }
188
189 #[inline]
193 pub fn struct_specifier(&self) -> Option<TypeSpecifier<'_>> {
194 self.internal_type().and_then(|ty| ty.struct_specifier())
195 }
196
197 #[inline]
201 pub fn enum_specifier(&self) -> Option<TypeSpecifier<'_>> {
202 self.internal_type().and_then(|ty| ty.enum_specifier())
203 }
204
205 #[inline]
209 pub fn contract_specifier(&self) -> Option<TypeSpecifier<'_>> {
210 self.internal_type().and_then(|ty| ty.contract_specifier())
211 }
212
213 #[inline]
215 pub fn is_simple_type(&self) -> bool {
216 self.components.is_empty()
217 }
218
219 #[inline]
221 pub fn is_complex_type(&self) -> bool {
222 !self.components.is_empty()
223 }
224
225 #[inline]
229 pub fn selector_type_raw(&self, s: &mut String) {
230 if self.components.is_empty() {
231 s.push_str(&self.ty);
232 } else {
233 crate::utils::params_abi_tuple(&self.components, s);
234 if let Some(suffix) = self.ty.strip_prefix("tuple") {
236 s.push_str(suffix);
237 }
238 }
239 }
240
241 #[inline]
244 pub fn full_selector_type_raw(&self, s: &mut String) {
245 if self.components.is_empty() {
246 s.push_str(&self.ty);
247 } else {
248 s.push_str("tuple");
249 crate::utils::params_tuple(&self.components, s);
250 if let Some(suffix) = self.ty.strip_prefix("tuple") {
252 s.push_str(suffix);
253 }
254 }
255 }
256
257 #[inline]
261 pub fn selector_type(&self) -> Cow<'_, str> {
262 if self.components.is_empty() {
263 Cow::Borrowed(&self.ty)
264 } else {
265 let mut s = String::with_capacity(self.components.len() * 32);
266 self.selector_type_raw(&mut s);
267 Cow::Owned(s)
268 }
269 }
270
271 #[inline]
272 fn borrowed_internal_type(&self) -> Option<BorrowedInternalType<'_>> {
273 self.internal_type().as_ref().map(|it| it.as_borrowed())
274 }
275
276 #[inline]
277 fn as_inner(&self) -> BorrowedParamInner<'_> {
278 BorrowedParamInner {
279 name: &self.name,
280 ty: &self.ty,
281 indexed: None,
282 internal_type: self.borrowed_internal_type(),
283 components: Cow::Borrowed(&self.components),
284 }
285 }
286
287 #[inline]
288 fn validate_fields(name: &str, ty: &str, has_components: bool) -> parser::Result<()> {
289 if !name.is_empty() && !parser::is_valid_identifier(name) {
290 return Err(Error::invalid_identifier_string(name));
291 }
292
293 if !has_components {
296 parser::TypeSpecifier::parse(ty)?;
297 } else {
298 if !ty.starts_with("tuple") {
301 return Err(Error::invalid_type_string(ty));
302 }
303 }
304 Ok(())
305 }
306}
307
308#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
313pub struct EventParam {
314 #[doc(hidden)]
325 pub ty: String,
326 #[doc(hidden)]
331 pub name: String,
332 pub indexed: bool,
335 pub components: Vec<Param>,
340 pub internal_type: Option<InternalType>,
344}
345
346impl fmt::Display for EventParam {
347 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348 if let Some(it) = &self.internal_type { it.fmt(f) } else { f.write_str(&self.ty) }?;
349 f.write_str(" ")?;
350 f.write_str(&self.name)
351 }
352}
353
354impl<'de> Deserialize<'de> for EventParam {
355 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
356 ParamInner::deserialize(deserializer).and_then(|inner| {
357 inner.validate_fields()?;
358 Ok(Self {
359 name: inner.name,
360 ty: inner.ty,
361 indexed: inner.indexed.unwrap_or(false),
362 internal_type: inner.internal_type,
363 components: inner.components,
364 })
365 })
366 }
367}
368
369impl Serialize for EventParam {
370 #[inline]
371 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
372 self.as_inner().serialize(serializer)
373 }
374}
375
376impl FromStr for EventParam {
377 type Err = parser::Error;
378
379 #[inline]
380 fn from_str(s: &str) -> Result<Self, Self::Err> {
381 Self::parse(s)
382 }
383}
384
385impl EventParam {
386 #[inline]
405 pub fn parse(input: &str) -> parser::Result<Self> {
406 ParameterSpecifier::parse(input).map(mk_eparam)
407 }
408
409 pub fn new(
411 name: &str,
412 ty: &str,
413 indexed: bool,
414 components: Vec<Param>,
415 internal_type: Option<InternalType>,
416 ) -> parser::Result<Self> {
417 Param::validate_fields(name, ty, !components.is_empty())?;
418 Ok(Self { name: name.into(), ty: ty.into(), indexed, components, internal_type })
419 }
420
421 #[inline]
423 pub const fn internal_type(&self) -> Option<&InternalType> {
424 self.internal_type.as_ref()
425 }
426
427 #[inline]
436 pub fn is_udt(&self) -> bool {
437 match self.internal_type().and_then(|it| it.as_other()) {
438 Some((contract, ty)) => contract.is_some() || (self.is_simple_type() && ty != self.ty),
439 _ => false,
440 }
441 }
442
443 #[inline]
445 pub const fn is_struct(&self) -> bool {
446 match self.internal_type() {
447 Some(ty) => ty.is_struct(),
448 None => false,
449 }
450 }
451
452 #[inline]
454 pub const fn is_enum(&self) -> bool {
455 match self.internal_type() {
456 Some(ty) => ty.is_enum(),
457 None => false,
458 }
459 }
460
461 #[inline]
463 pub const fn is_contract(&self) -> bool {
464 match self.internal_type() {
465 Some(ty) => ty.is_contract(),
466 None => false,
467 }
468 }
469
470 #[inline]
474 pub fn udt_specifier(&self) -> Option<TypeSpecifier<'_>> {
475 if !self.is_udt() {
477 return None;
478 }
479 self.internal_type().and_then(|ty| ty.other_specifier())
480 }
481
482 #[inline]
486 pub fn struct_specifier(&self) -> Option<TypeSpecifier<'_>> {
487 self.internal_type().and_then(|ty| ty.struct_specifier())
488 }
489
490 #[inline]
494 pub fn enum_specifier(&self) -> Option<TypeSpecifier<'_>> {
495 self.internal_type().and_then(|ty| ty.enum_specifier())
496 }
497
498 #[inline]
502 pub fn contract_specifier(&self) -> Option<TypeSpecifier<'_>> {
503 self.internal_type().and_then(|ty| ty.contract_specifier())
504 }
505
506 #[inline]
508 pub fn is_simple_type(&self) -> bool {
509 self.components.is_empty()
510 }
511
512 #[inline]
514 pub fn is_complex_type(&self) -> bool {
515 !self.components.is_empty()
516 }
517
518 #[inline]
522 pub fn selector_type_raw(&self, s: &mut String) {
523 if self.components.is_empty() {
524 s.push_str(&self.ty);
525 } else {
526 crate::utils::params_abi_tuple(&self.components, s);
527 if let Some(suffix) = self.ty.strip_prefix("tuple") {
529 s.push_str(suffix);
530 }
531 }
532 }
533
534 #[inline]
537 pub fn full_selector_type_raw(&self, s: &mut String) {
538 if self.components.is_empty() {
539 s.push_str(&self.ty);
540 } else {
541 s.push_str("tuple");
542 crate::utils::params_tuple(&self.components, s);
543 if let Some(suffix) = self.ty.strip_prefix("tuple") {
545 s.push_str(suffix);
546 }
547 }
548 }
549
550 #[inline]
554 pub fn selector_type(&self) -> Cow<'_, str> {
555 if self.components.is_empty() {
556 Cow::Borrowed(&self.ty)
557 } else {
558 let mut s = String::with_capacity(self.components.len() * 32);
559 self.selector_type_raw(&mut s);
560 Cow::Owned(s)
561 }
562 }
563
564 #[inline]
565 fn borrowed_internal_type(&self) -> Option<BorrowedInternalType<'_>> {
566 self.internal_type().as_ref().map(|it| it.as_borrowed())
567 }
568
569 #[inline]
570 fn as_inner(&self) -> BorrowedParamInner<'_> {
571 BorrowedParamInner {
572 name: &self.name,
573 ty: &self.ty,
574 indexed: Some(self.indexed),
575 internal_type: self.borrowed_internal_type(),
576 components: Cow::Borrowed(&self.components),
577 }
578 }
579}
580
581#[derive(Deserialize)]
582struct ParamInner {
583 #[serde(default)]
584 name: String,
585 #[serde(rename = "type")]
586 ty: String,
587 #[serde(default, skip_serializing_if = "Option::is_none")]
588 indexed: Option<bool>,
589 #[serde(rename = "internalType", default, skip_serializing_if = "Option::is_none")]
590 internal_type: Option<InternalType>,
591 #[serde(default, skip_serializing_if = "Vec::is_empty")]
592 components: Vec<Param>,
593}
594
595impl Serialize for ParamInner {
596 #[inline]
597 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
598 self.as_borrowed().serialize(serializer)
599 }
600}
601
602impl ParamInner {
603 #[inline]
604 fn validate_fields<E: serde::de::Error>(&self) -> Result<(), E> {
605 self.as_borrowed().validate_fields()
606 }
607
608 #[inline]
609 fn as_borrowed(&self) -> BorrowedParamInner<'_> {
610 BorrowedParamInner {
611 name: &self.name,
612 ty: &self.ty,
613 indexed: self.indexed,
614 internal_type: self.internal_type.as_ref().map(InternalType::as_borrowed),
615 components: Cow::Borrowed(&self.components),
616 }
617 }
618}
619
620#[derive(Serialize, Deserialize)]
621struct BorrowedParamInner<'a> {
622 #[serde(default)]
623 name: &'a str,
624 #[serde(rename = "type")]
625 ty: &'a str,
626 #[serde(default, skip_serializing_if = "Option::is_none")]
627 indexed: Option<bool>,
628 #[serde(rename = "internalType", default, skip_serializing_if = "Option::is_none")]
629 internal_type: Option<BorrowedInternalType<'a>>,
630 #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
631 components: Cow<'a, [Param]>,
632}
633
634impl BorrowedParamInner<'_> {
635 fn validate_fields<E: serde::de::Error>(&self) -> Result<(), E> {
636 validate_identifier(self.name)?;
637
638 if self.components.is_empty() {
641 if parser::TypeSpecifier::parse(self.ty).is_err() {
642 return Err(E::invalid_value(
643 Unexpected::Str(self.ty),
644 &"a valid Solidity type specifier",
645 ));
646 }
647 } else {
648 if !self.ty.starts_with("tuple") {
651 return Err(E::invalid_value(
652 Unexpected::Str(self.ty),
653 &"a string prefixed with `tuple`, optionally followed by a sequence of `[]` or `[k]` with integers `k`",
654 ));
655 }
656 }
657
658 Ok(())
659 }
660}
661
662#[cfg(test)]
663mod tests {
664 use super::*;
665
666 #[test]
667 fn param_from_json() {
668 let param = r#"{
669 "internalType": "string",
670 "name": "reason",
671 "type": "string"
672 }"#;
673 let expected = Param {
674 name: "reason".into(),
675 ty: "string".into(),
676 internal_type: Some(InternalType::Other { contract: None, ty: "string".into() }),
677 components: vec![],
678 };
679
680 assert_eq!(serde_json::from_str::<Param>(param).unwrap(), expected);
681
682 let param_value = serde_json::from_str::<serde_json::Value>(param).unwrap();
683 assert_eq!(serde_json::from_value::<Param>(param_value).unwrap(), expected);
684
685 #[cfg(feature = "std")]
686 {
687 let reader = std::io::Cursor::new(param);
688 assert_eq!(serde_json::from_reader::<_, Param>(reader).unwrap(), expected);
689 }
690 }
691
692 #[test]
693 fn param_from_new() {
694 let param = Param::new("something", "string", vec![], None);
695 assert_eq!(
696 param,
697 Ok(Param {
698 name: "something".into(),
699 ty: "string".into(),
700 components: vec![],
701 internal_type: None,
702 })
703 );
704
705 let err_not_a_type = Param::new("something", "not a type", vec![], None);
706 assert!(err_not_a_type.is_err());
707
708 let err_not_tuple = Param::new("something", "string", vec![param.unwrap()], None);
709 assert!(err_not_tuple.is_err())
710 }
711}