#![allow(clippy::upper_case_acronyms)]
use std::{convert::TryFrom, fmt::Display, marker::PhantomData, str::FromStr};
use serde::de::Error;
use fvm_shared::address::{Address, Payload};
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct TAddress<T> {
addr: Address,
_phantom: PhantomData<T>,
}
impl<T> TAddress<T> {
pub fn new(addr: Address) -> Self {
Self {
addr,
_phantom: Default::default(),
}
}
#[allow(dead_code)]
pub fn to_bytes(&self) -> Vec<u8> {
self.addr.to_bytes()
}
#[allow(dead_code)]
pub fn addr(&self) -> &Address {
&self.addr
}
}
trait RawAddress {
fn is_compatible(addr: Address) -> bool;
}
macro_rules! raw_address_types {
($($typ:ident),+) => {
$(
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct $typ;
impl RawAddress for $typ {
fn is_compatible(addr: Address) -> bool {
match addr.payload() {
Payload::$typ(_) => true,
_ => false
}
}
}
)*
};
}
raw_address_types! {
ID,
Secp256k1,
Actor,
BLS
}
impl<T> From<TAddress<T>> for Address {
fn from(t: TAddress<T>) -> Self {
t.addr
}
}
impl<A: RawAddress> TryFrom<Address> for TAddress<A> {
type Error = fvm_shared::address::Error;
fn try_from(value: Address) -> Result<Self, Self::Error> {
if !A::is_compatible(value) {
return Err(fvm_shared::address::Error::InvalidPayload);
}
Ok(Self {
addr: value,
_phantom: PhantomData,
})
}
}
impl<T> serde::Serialize for TAddress<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.addr.serialize(serializer)
}
}
impl<'d, T> serde::Deserialize<'d> for TAddress<T>
where
Self: TryFrom<Address>,
<Self as TryFrom<Address>>::Error: Display,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'d>,
{
let raw = Address::deserialize(deserializer)?;
match Self::try_from(raw) {
Ok(addr) => Ok(addr),
Err(e) => Err(D::Error::custom(format!("wrong address type: {e}"))),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct TAddressKey<T>(pub TAddress<T>);
impl<T> serde::Serialize for TAddressKey<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.addr.to_string().serialize(serializer)
}
}
impl<'d, T> serde::Deserialize<'d> for TAddressKey<T>
where
TAddress<T>: TryFrom<Address>,
<TAddress<T> as TryFrom<Address>>::Error: Display,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'d>,
{
let str = String::deserialize(deserializer)?;
let raw = Address::from_str(&str)
.map_err(|e| D::Error::custom(format!("not an address string: {e:?}")))?;
let addr = TAddress::<T>::try_from(raw)
.map_err(|e| D::Error::custom(format!("wrong address type: {e}")))?;
Ok(Self(addr))
}
}