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