1#[cfg(feature = "epee")]
7use cuprate_epee_encoding::{error, macros::bytes, EpeeValue, Marker};
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(feature = "serde", derive(Serialize))]
19#[cfg_attr(feature = "serde", serde(transparent))]
20#[repr(transparent)]
21pub struct HexBytes<const N: usize>(
22 #[cfg_attr(feature = "serde", serde(with = "hex::serde"))] pub [u8; N],
23);
24
25#[cfg(feature = "serde")]
26impl<'de, const N: usize> Deserialize<'de> for HexBytes<N>
27where
28 [u8; N]: hex::FromHex,
29 <[u8; N] as hex::FromHex>::Error: std::fmt::Display,
30{
31 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
32 where
33 D: serde::Deserializer<'de>,
34 {
35 Ok(Self(hex::serde::deserialize(deserializer)?))
36 }
37}
38
39#[cfg(feature = "epee")]
40impl<const N: usize> EpeeValue for HexBytes<N> {
41 const MARKER: Marker = <[u8; N] as EpeeValue>::MARKER;
42
43 fn read<B: bytes::Buf>(r: &mut B, marker: &Marker) -> error::Result<Self> {
44 Ok(Self(<[u8; N] as EpeeValue>::read(r, marker)?))
45 }
46
47 fn write<B: bytes::BufMut>(self, w: &mut B) -> error::Result<()> {
48 <[u8; N] as EpeeValue>::write(self.0, w)
49 }
50}
51
52impl<const N: usize> Default for HexBytes<N> {
54 fn default() -> Self {
55 Self([0; N])
56 }
57}
58
59#[cfg(test)]
60mod test {
61 use super::*;
62
63 #[test]
64 fn hex_bytes_32() {
65 let hash = [1; 32];
66 let hex_bytes = HexBytes::<32>(hash);
67 let expected_json = r#""0101010101010101010101010101010101010101010101010101010101010101""#;
68
69 let to_string = serde_json::to_string(&hex_bytes).unwrap();
70 assert_eq!(to_string, expected_json);
71
72 let from_str = serde_json::from_str::<HexBytes<32>>(expected_json).unwrap();
73 assert_eq!(hex_bytes, from_str);
74 }
75}