1use alloc::{borrow::Cow, string::String};
2use alloy_primitives::{Selector, B256};
3use alloy_sol_types::Error as SolTypesError;
4use core::fmt;
5use hex::FromHexError;
6use parser::Error as TypeParserError;
7
8pub type Result<T, E = Error> = core::result::Result<T, E>;
10
11#[derive(Clone, Debug, PartialEq)]
15pub enum Error {
16 #[cfg(feature = "eip712")]
18 MissingType(String),
19 #[cfg(feature = "eip712")]
21 CircularDependency(String),
22 #[cfg(feature = "eip712")]
24 InvalidPropertyDefinition(String),
25
26 TypeMismatch {
28 expected: String,
30 actual: String,
32 },
33 EncodeLengthMismatch {
35 expected: usize,
37 actual: usize,
39 },
40
41 TopicLengthMismatch {
43 expected: usize,
45 actual: usize,
47 },
48
49 SelectorMismatch {
51 expected: Selector,
53 actual: Selector,
55 },
56
57 EventSignatureMismatch {
59 expected: B256,
61 actual: B256,
63 },
64
65 Hex(hex::FromHexError),
67 TypeParser(TypeParserError),
69 SolTypes(SolTypesError),
71}
72
73impl From<FromHexError> for Error {
74 #[inline]
75 fn from(e: FromHexError) -> Self {
76 Self::Hex(e)
77 }
78}
79
80impl From<SolTypesError> for Error {
81 #[inline]
82 fn from(e: SolTypesError) -> Self {
83 Self::SolTypes(e)
84 }
85}
86
87impl From<TypeParserError> for Error {
88 #[inline]
89 fn from(e: TypeParserError) -> Self {
90 Self::TypeParser(e)
91 }
92}
93
94impl From<alloc::collections::TryReserveError> for Error {
95 #[inline]
96 fn from(value: alloc::collections::TryReserveError) -> Self {
97 Self::SolTypes(value.into())
98 }
99}
100
101impl core::error::Error for Error {
102 #[inline]
103 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
104 match self {
105 Self::Hex(e) => Some(e),
106 Self::TypeParser(e) => Some(e),
107 Self::SolTypes(e) => Some(e),
108 _ => None,
109 }
110 }
111}
112
113impl fmt::Display for Error {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 #[cfg(feature = "eip712")]
117 Self::MissingType(name) => write!(f, "missing type in type resolution: {name}"),
118 #[cfg(feature = "eip712")]
119 Self::CircularDependency(dep) => write!(f, "circular dependency: {dep}"),
120 #[cfg(feature = "eip712")]
121 Self::InvalidPropertyDefinition(def) => write!(f, "invalid property definition: {def}"),
122
123 Self::TypeMismatch { expected, actual } => write!(
124 f,
125 "type mismatch: expected type {expected:?}, got value with type {actual:?}",
126 ),
127 &Self::EncodeLengthMismatch { expected, actual } => {
128 write!(f, "encode length mismatch: expected {expected} types, got {actual}",)
129 }
130
131 &Self::TopicLengthMismatch { expected, actual } => {
132 write!(f, "invalid log topic list length: expected {expected} topics, got {actual}",)
133 }
134 Self::EventSignatureMismatch { expected, actual } => {
135 write!(f, "invalid event signature: expected {expected}, got {actual}",)
136 }
137 Self::SelectorMismatch { expected, actual } => {
138 write!(f, "selector mismatch: expected {expected}, got {actual}",)
139 }
140 Self::Hex(e) => e.fmt(f),
141 Self::TypeParser(e) => e.fmt(f),
142 Self::SolTypes(e) => e.fmt(f),
143 }
144 }
145}
146
147impl Error {
148 pub fn custom(s: impl Into<Cow<'static, str>>) -> Self {
150 Self::SolTypes(SolTypesError::custom(s))
151 }
152
153 #[cfg(feature = "eip712")]
154 pub(crate) fn eip712_coerce(expected: &crate::DynSolType, actual: &serde_json::Value) -> Self {
155 #[allow(unused_imports)]
156 use alloc::string::ToString;
157 Self::TypeMismatch { expected: expected.to_string(), actual: actual.to_string() }
158 }
159
160 #[cfg(feature = "eip712")]
161 pub(crate) fn invalid_property_def(def: &str) -> Self {
162 Self::InvalidPropertyDefinition(def.into())
163 }
164
165 #[cfg(feature = "eip712")]
166 pub(crate) fn missing_type(name: &str) -> Self {
167 Self::MissingType(name.into())
168 }
169
170 #[cfg(feature = "eip712")]
171 pub(crate) fn circular_dependency(dep: &str) -> Self {
172 Self::CircularDependency(dep.into())
173 }
174}