@@ -52,6 +52,7 @@ use std::ops::Deref;
5252use std:: str:: FromStr ;
5353
5454use bitcoin_hashes:: hex;
55+ use bitcoin_hashes:: hex:: DisplayHex ;
5556use bitcoin_hashes:: sha256;
5657use bitcoin_hashes:: sha512_256;
5758use bitcoin_hashes:: Hash ;
@@ -77,6 +78,51 @@ pub trait AccumulatorHash:
7778 R : std:: io:: Read ;
7879}
7980
81+ /// (de)serialize as hex if the (de)serializer is human readable.
82+ #[ cfg( feature = "with-serde" ) ]
83+ mod serde_hex {
84+ pub fn serialize < S , T > ( data : T , serializer : S ) -> Result < S :: Ok , S :: Error >
85+ where
86+ S : serde:: Serializer ,
87+ T : serde:: Serialize + bitcoin_hashes:: hex:: DisplayHex ,
88+ {
89+ if serializer. is_human_readable ( ) {
90+ serializer. collect_str ( & format_args ! ( "{:x}" , data. as_hex( ) ) )
91+ } else {
92+ data. serialize ( serializer)
93+ }
94+ }
95+
96+ pub fn deserialize < ' de , D , T > ( deserializer : D ) -> Result < T , D :: Error >
97+ where
98+ D : serde:: Deserializer < ' de > ,
99+ T : serde:: Deserialize < ' de > + bitcoin_hashes:: hex:: FromHex ,
100+ {
101+ struct HexVisitor < T > ( std:: marker:: PhantomData < T > ) ;
102+
103+ impl < ' de , T > serde:: de:: Visitor < ' de > for HexVisitor < T >
104+ where
105+ T : bitcoin_hashes:: hex:: FromHex ,
106+ {
107+ type Value = T ;
108+
109+ fn expecting ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
110+ f. write_str ( "an ASCII hex string" )
111+ }
112+
113+ fn visit_str < E : serde:: de:: Error > ( self , data : & str ) -> Result < Self :: Value , E > {
114+ T :: from_hex ( data) . map_err ( serde:: de:: Error :: custom)
115+ }
116+ }
117+
118+ if deserializer. is_human_readable ( ) {
119+ deserializer. deserialize_map ( HexVisitor ( std:: marker:: PhantomData ) )
120+ } else {
121+ T :: deserialize ( deserializer)
122+ }
123+ }
124+ }
125+
80126#[ derive( Eq , PartialEq , Copy , Clone , Hash , PartialOrd , Ord ) ]
81127#[ cfg_attr( feature = "with-serde" , derive( Serialize , Deserialize ) ) ]
82128/// AccumulatorHash is a wrapper around a 32 byte array that represents a hash of a node in the tree.
@@ -94,7 +140,7 @@ pub enum BitcoinNodeHash {
94140 #[ default]
95141 Empty ,
96142 Placeholder ,
97- Some ( [ u8 ; 32 ] ) ,
143+ Some ( # [ cfg_attr ( feature = "with-serde" , serde ( with = "serde_hex" ) ) ] [ u8 ; 32 ] ) ,
98144}
99145
100146#[ deprecated( since = "0.4.0" , note = "Please use BitcoinNodeHash instead." ) ]
@@ -114,11 +160,7 @@ impl Deref for BitcoinNodeHash {
114160impl Display for BitcoinNodeHash {
115161 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: result:: Result < ( ) , std:: fmt:: Error > {
116162 if let BitcoinNodeHash :: Some ( ref inner) = self {
117- let mut s = String :: new ( ) ;
118- for byte in inner. iter ( ) {
119- s. push_str ( & format ! ( "{:02x}" , byte) ) ;
120- }
121- write ! ( f, "{}" , s)
163+ Display :: fmt ( & inner. as_hex ( ) , f)
122164 } else {
123165 write ! ( f, "empty" )
124166 }
@@ -130,13 +172,7 @@ impl Debug for BitcoinNodeHash {
130172 match self {
131173 BitcoinNodeHash :: Empty => write ! ( f, "empty" ) ,
132174 BitcoinNodeHash :: Placeholder => write ! ( f, "placeholder" ) ,
133- BitcoinNodeHash :: Some ( ref inner) => {
134- let mut s = String :: new ( ) ;
135- for byte in inner. iter ( ) {
136- s. push_str ( & format ! ( "{:02x}" , byte) ) ;
137- }
138- write ! ( f, "{}" , s)
139- }
175+ BitcoinNodeHash :: Some ( ref inner) => Debug :: fmt ( & inner. as_hex ( ) , f) ,
140176 }
141177 }
142178}
0 commit comments