use crate::prelude::*;
pub struct Base58<ALPHABET: Alphabet = Standard>(PhantomData<ALPHABET>);
impl<T, ALPHABET> SerializeAs<T> for Base58<ALPHABET>
where
T: AsRef<[u8]>,
ALPHABET: Alphabet,
{
fn serialize_as<S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
::bs58::encode::EncodeBuilder::new(source, ALPHABET::CHARSET)
.into_string()
.serialize(serializer)
}
}
impl<'de, T, ALPHABET> DeserializeAs<'de, T> for Base58<ALPHABET>
where
T: TryFrom<Vec<u8>>,
ALPHABET: Alphabet,
{
fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
{
struct Helper<T, ALPHABET>(PhantomData<(T, ALPHABET)>);
impl<T, ALPHABET> Visitor<'_> for Helper<T, ALPHABET>
where
T: TryFrom<Vec<u8>>,
ALPHABET: Alphabet,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a base58 encoded string")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: DeError,
{
let bytes = ::bs58::decode::DecodeBuilder::new(value, ALPHABET::CHARSET)
.into_vec()
.map_err(DeError::custom)?;
let length = bytes.len();
bytes.try_into().map_err(|_e: T::Error| {
DeError::custom(format_args!(
"Can't convert a Byte Vector of length {length} to the output type."
))
})
}
}
deserializer.deserialize_str(Helper::<T, ALPHABET>(PhantomData))
}
}
mod sealed {
pub trait Sealed {}
impl Sealed for super::Bitcoin {}
impl Sealed for super::Monero {}
impl Sealed for super::Ripple {}
impl Sealed for super::Flickr {}
}
pub trait Alphabet: sealed::Sealed {
const CHARSET: &'static ::bs58::Alphabet;
}
pub type Standard = Bitcoin;
pub struct Bitcoin;
impl Alphabet for Bitcoin {
const CHARSET: &'static bs58::Alphabet = ::bs58::Alphabet::BITCOIN;
}
pub struct Monero;
impl Alphabet for Monero {
const CHARSET: &'static bs58::Alphabet = ::bs58::Alphabet::MONERO;
}
pub struct Ripple;
impl Alphabet for Ripple {
const CHARSET: &'static bs58::Alphabet = ::bs58::Alphabet::RIPPLE;
}
pub struct Flickr;
impl Alphabet for Flickr {
const CHARSET: &'static bs58::Alphabet = ::bs58::Alphabet::FLICKR;
}