1use serde::{Deserialize, Deserializer, Serialize};
18use std::fmt::{self, Display};
19
20pub trait HashType: Sized {
21 fn bytes(&self) -> &[u8];
22 fn from_str(v: &str) -> anyhow::Result<Self>;
23}
24
25macro_rules! hash_type_impl {
26 ($name:ty) => {
27 impl HashType for $name {
28 fn bytes(&self) -> &[u8] {
29 self.as_bytes()
30 }
31 fn from_str(v: &str) -> anyhow::Result<Self> {
32 Ok(v.parse()?)
33 }
34 }
35 };
36}
37
38hash_type_impl!(monero::util::address::PaymentId);
39hash_type_impl!(monero::cryptonote::hash::Hash);
40
41impl HashType for Vec<u8> {
42 fn bytes(&self) -> &[u8] {
43 self
44 }
45 fn from_str(v: &str) -> anyhow::Result<Self> {
46 Ok(hex::decode(v)?)
47 }
48}
49
50#[derive(Clone, Debug)]
51pub struct HashString<T>(pub T);
52
53impl<T> Display for HashString<T>
54where
55 T: HashType,
56{
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(f, "{}", hex::encode(self.0.bytes()))
59 }
60}
61
62impl<T> Serialize for HashString<T>
63where
64 T: HashType,
65{
66 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67 where
68 S: serde::ser::Serializer,
69 {
70 serializer.serialize_str(&self.to_string())
71 }
72}
73
74impl<'de, T> Deserialize<'de> for HashString<T>
75where
76 T: HashType,
77{
78 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79 where
80 D: Deserializer<'de>,
81 {
82 let s = String::deserialize(deserializer)?;
83 Ok(Self(T::from_str(&s).map_err(serde::de::Error::custom)?))
84 }
85}