use alloc::{borrow::Cow, boxed::Box, string::ToString};
use core::{convert::Infallible, fmt::Display};
#[derive(Debug, thiserror::Error)]
#[error("{msg}")]
pub struct ValueError<T> {
msg: Cow<'static, str>,
value: Box<T>,
}
impl<T> ValueError<T> {
pub fn new(value: T, msg: impl Display) -> Self {
Self { msg: Cow::Owned(msg.to_string()), value: Box::new(value) }
}
pub fn new_static(value: T, msg: &'static str) -> Self {
Self { msg: Cow::Borrowed(msg), value: Box::new(value) }
}
pub fn convert<U>(self) -> ValueError<U>
where
U: From<T>,
{
self.map(U::from)
}
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ValueError<U> {
ValueError { msg: self.msg, value: Box::new(f(*self.value)) }
}
pub fn into_value(self) -> T {
*self.value
}
pub const fn value(&self) -> &T {
&self.value
}
}
#[derive(Debug, thiserror::Error)]
#[error("Unsupported transaction type: {0}")]
pub struct UnsupportedTransactionType<TxType: Display>(TxType);
impl<TxType: Display> UnsupportedTransactionType<TxType> {
pub const fn new(ty: TxType) -> Self {
Self(ty)
}
pub fn into_inner(self) -> TxType {
self.0
}
}
impl<TxType: Display> AsRef<TxType> for UnsupportedTransactionType<TxType> {
fn as_ref(&self) -> &TxType {
&self.0
}
}
impl<TxType: Display> From<Infallible> for UnsupportedTransactionType<TxType> {
fn from(value: Infallible) -> Self {
match value {}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::TxType;
#[test]
fn test_unsupported_tx_type_error_displays_itself_and_the_type() {
let error = UnsupportedTransactionType::new(TxType::Eip2930);
let actual_msg = error.to_string();
let expected_msg = "Unsupported transaction type: EIP-2930";
assert_eq!(actual_msg, expected_msg);
}
}