1use crate::{
2    InternalType,
3    internal_type::BorrowedInternalType,
4    utils::{mk_eparam, mk_param, validate_identifier},
5};
6use alloc::{borrow::Cow, string::String, vec::Vec};
7use core::{fmt, str::FromStr};
8use parser::{Error, ParameterSpecifier, TypeSpecifier};
9use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Unexpected};
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    #[cfg(all(feature = "std", feature = "serde_json"))]
668    fn param_from_json() {
669        let param = r#"{
670            "internalType": "string",
671            "name": "reason",
672            "type": "string"
673        }"#;
674        let expected = Param {
675            name: "reason".into(),
676            ty: "string".into(),
677            internal_type: Some(InternalType::Other { contract: None, ty: "string".into() }),
678            components: vec![],
679        };
680
681        assert_eq!(serde_json::from_str::<Param>(param).unwrap(), expected);
682
683        let param_value = serde_json::from_str::<serde_json::Value>(param).unwrap();
684        assert_eq!(serde_json::from_value::<Param>(param_value).unwrap(), expected);
685
686        #[cfg(feature = "std")]
687        {
688            let reader = std::io::Cursor::new(param);
689            assert_eq!(serde_json::from_reader::<_, Param>(reader).unwrap(), expected);
690        }
691    }
692
693    #[test]
694    fn param_from_new() {
695        let param = Param::new("something", "string", vec![], None);
696        assert_eq!(
697            param,
698            Ok(Param {
699                name: "something".into(),
700                ty: "string".into(),
701                components: vec![],
702                internal_type: None,
703            })
704        );
705
706        let err_not_a_type = Param::new("something", "not a type", vec![], None);
707        assert!(err_not_a_type.is_err());
708
709        let err_not_tuple = Param::new("something", "string", vec![param.unwrap()], None);
710        assert!(err_not_tuple.is_err())
711    }
712}