@@ -4,7 +4,7 @@ use crate::utils::hex_to_uint256;
44
55use bitcoin:: blockdata:: block:: { Block , BlockHeader } ;
66use bitcoin:: consensus:: encode;
7- use bitcoin:: hash_types:: { BlockHash , TxMerkleNode } ;
7+ use bitcoin:: hash_types:: { BlockHash , TxMerkleNode , Txid } ;
88use bitcoin:: hashes:: hex:: { ToHex , FromHex } ;
99
1010use serde:: Deserialize ;
@@ -156,11 +156,37 @@ impl TryInto<(BlockHash, Option<u32>)> for JsonResponse {
156156 }
157157}
158158
159+ impl TryInto < Txid > for JsonResponse {
160+ type Error = std:: io:: Error ;
161+ fn try_into ( self ) -> std:: io:: Result < Txid > {
162+ match self . 0 . as_str ( ) {
163+ None => Err ( std:: io:: Error :: new (
164+ std:: io:: ErrorKind :: InvalidData ,
165+ "expected JSON string" ,
166+ ) ) ,
167+ Some ( hex_data) => match Vec :: < u8 > :: from_hex ( hex_data) {
168+ Err ( _) => Err ( std:: io:: Error :: new (
169+ std:: io:: ErrorKind :: InvalidData ,
170+ "invalid hex data" ,
171+ ) ) ,
172+ Ok ( txid_data) => match encode:: deserialize ( & txid_data) {
173+ Err ( _) => Err ( std:: io:: Error :: new (
174+ std:: io:: ErrorKind :: InvalidData ,
175+ "invalid txid" ,
176+ ) ) ,
177+ Ok ( txid) => Ok ( txid) ,
178+ } ,
179+ } ,
180+ }
181+ }
182+ }
183+
159184#[ cfg( test) ]
160185pub ( crate ) mod tests {
161186 use super :: * ;
162187 use bitcoin:: blockdata:: constants:: genesis_block;
163188 use bitcoin:: consensus:: encode;
189+ use bitcoin:: hashes:: Hash ;
164190 use bitcoin:: network:: constants:: Network ;
165191
166192 /// Converts from `BlockHeaderData` into a `GetHeaderResponse` JSON value.
@@ -469,4 +495,50 @@ pub(crate) mod tests {
469495 } ,
470496 }
471497 }
498+
499+ #[ test]
500+ fn into_txid_from_json_response_with_unexpected_type ( ) {
501+ let response = JsonResponse ( serde_json:: json!( { "result" : "foo" } ) ) ;
502+ match TryInto :: < Txid > :: try_into ( response) {
503+ Err ( e) => {
504+ assert_eq ! ( e. kind( ) , std:: io:: ErrorKind :: InvalidData ) ;
505+ assert_eq ! ( e. get_ref( ) . unwrap( ) . to_string( ) , "expected JSON string" ) ;
506+ }
507+ Ok ( _) => panic ! ( "Expected error" ) ,
508+ }
509+ }
510+
511+ #[ test]
512+ fn into_txid_from_json_response_with_invalid_hex_data ( ) {
513+ let response = JsonResponse ( serde_json:: json!( "foobar" ) ) ;
514+ match TryInto :: < Txid > :: try_into ( response) {
515+ Err ( e) => {
516+ assert_eq ! ( e. kind( ) , std:: io:: ErrorKind :: InvalidData ) ;
517+ assert_eq ! ( e. get_ref( ) . unwrap( ) . to_string( ) , "invalid hex data" ) ;
518+ }
519+ Ok ( _) => panic ! ( "Expected error" ) ,
520+ }
521+ }
522+
523+ #[ test]
524+ fn into_txid_from_json_response_with_invalid_txid_data ( ) {
525+ let response = JsonResponse ( serde_json:: json!( "abcd" ) ) ;
526+ match TryInto :: < Txid > :: try_into ( response) {
527+ Err ( e) => {
528+ assert_eq ! ( e. kind( ) , std:: io:: ErrorKind :: InvalidData ) ;
529+ assert_eq ! ( e. get_ref( ) . unwrap( ) . to_string( ) , "invalid txid" ) ;
530+ }
531+ Ok ( _) => panic ! ( "Expected error" ) ,
532+ }
533+ }
534+
535+ #[ test]
536+ fn into_txid_from_json_response_with_valid_txid_data ( ) {
537+ let target_txid = Txid :: from_slice ( & [ 1 ; 32 ] ) . unwrap ( ) ;
538+ let response = JsonResponse ( serde_json:: json!( encode:: serialize_hex( & target_txid) ) ) ;
539+ match TryInto :: < Txid > :: try_into ( response) {
540+ Err ( e) => panic ! ( "Unexpected error: {:?}" , e) ,
541+ Ok ( txid) => assert_eq ! ( txid, target_txid) ,
542+ }
543+ }
472544}
0 commit comments