@@ -5,7 +5,7 @@ use diesel::serialize::{Output, ToSql};
55use diesel:: sql_types:: Timestamptz ;
66use diesel:: sql_types:: { Bytea , Nullable , Text } ;
77use diesel_derives:: { AsExpression , FromSqlRow } ;
8- use serde:: Deserialize ;
8+ use serde:: { Deserialize , Deserializer } ;
99use std:: convert:: TryFrom ;
1010use std:: time:: Duration ;
1111use std:: { fmt, str:: FromStr } ;
@@ -21,7 +21,7 @@ use crate::prelude::{r, BigInt, TryFromValue, Value, ValueMap};
2121use crate :: util:: stable_hash_glue:: { impl_stable_hash, AsBytes } ;
2222
2323/// A simple marker for byte arrays that are really block hashes
24- #[ derive( Clone , Default , PartialEq , Eq , Hash , FromSqlRow , AsExpression , Deserialize ) ]
24+ #[ derive( Clone , Default , PartialEq , Eq , Hash , FromSqlRow , AsExpression ) ]
2525#[ diesel( sql_type = Bytea ) ]
2626pub struct BlockHash ( pub Box < [ u8 ] > ) ;
2727
@@ -49,6 +49,16 @@ impl BlockHash {
4949 }
5050}
5151
52+ impl < ' de > Deserialize < ' de > for BlockHash {
53+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
54+ where
55+ D : Deserializer < ' de > ,
56+ {
57+ let s: String = Deserialize :: deserialize ( deserializer) ?;
58+ BlockHash :: from_str ( & s) . map_err ( serde:: de:: Error :: custom)
59+ }
60+ }
61+
5262impl CheapClone for BlockHash {
5363 fn cheap_clone ( & self ) -> Self {
5464 Self ( self . 0 . clone ( ) )
@@ -331,9 +341,25 @@ impl From<BlockPtr> for BlockNumber {
331341 }
332342}
333343
344+ fn deserialize_block_number < ' de , D > ( deserializer : D ) -> Result < BlockNumber , D :: Error >
345+ where
346+ D : Deserializer < ' de > ,
347+ {
348+ let s: String = Deserialize :: deserialize ( deserializer) ?;
349+
350+ if s. starts_with ( "0x" ) {
351+ let s = s. trim_start_matches ( "0x" ) ;
352+ i32:: from_str_radix ( s, 16 ) . map_err ( serde:: de:: Error :: custom)
353+ } else {
354+ i32:: from_str ( & s) . map_err ( serde:: de:: Error :: custom)
355+ }
356+ }
357+
334358#[ derive( Clone , PartialEq , Eq , Hash , Deserialize ) ]
359+ #[ serde( rename_all = "camelCase" ) ]
335360pub struct BlockPtrExt {
336361 pub hash : BlockHash ,
362+ #[ serde( deserialize_with = "deserialize_block_number" ) ]
337363 pub number : BlockNumber ,
338364 pub parent_hash : BlockHash ,
339365 pub timestamp : U256 ,
@@ -577,3 +603,65 @@ impl ToSql<Timestamptz, Pg> for BlockTime {
577603 <Timestamp as ToSql < Timestamptz , Pg > >:: to_sql ( & self . 0 , out)
578604 }
579605}
606+
607+ #[ cfg( test) ]
608+ mod tests {
609+ use super :: * ;
610+ use serde_json;
611+
612+ #[ test]
613+ fn test_blockhash_deserialization ( ) {
614+ let json_data = "\" 0x8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac\" " ;
615+
616+ let block_hash: BlockHash =
617+ serde_json:: from_str ( json_data) . expect ( "Deserialization failed" ) ;
618+
619+ let expected_bytes =
620+ hex:: decode ( "8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac" )
621+ . expect ( "Hex decoding failed" ) ;
622+
623+ assert_eq ! (
624+ * block_hash. 0 , expected_bytes,
625+ "BlockHash does not match expected bytes"
626+ ) ;
627+ }
628+
629+ #[ test]
630+ fn test_block_ptr_ext_deserialization ( ) {
631+ // JSON data with a hex string for BlockNumber
632+ let json_data = r#"
633+ {
634+ "hash": "0x8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac",
635+ "number": "0x2A",
636+ "parentHash": "0xabc123",
637+ "timestamp": "123456789012345678901234567890"
638+ }
639+ "# ;
640+
641+ // Deserialize the JSON string into a BlockPtrExt
642+ let block_ptr_ext: BlockPtrExt =
643+ serde_json:: from_str ( json_data) . expect ( "Deserialization failed" ) ;
644+
645+ // Verify the deserialized values
646+ assert_eq ! ( block_ptr_ext. number, 42 ) ; // 0x2A in hex is 42 in decimal
647+ }
648+
649+ #[ test]
650+ fn test_invalid_block_number_deserialization ( ) {
651+ let invalid_json_data = r#"
652+ {
653+ "hash": "0x8186da3ec5590631ae7b9415ce58548cb98c7f1dc68c5ea1c519a3f0f6a25aac",
654+ "number": "invalid_hex_string",
655+ "parentHash": "0xabc123",
656+ "timestamp": "123456789012345678901234567890"
657+ }
658+ "# ;
659+
660+ let result: Result < BlockPtrExt , _ > = serde_json:: from_str ( invalid_json_data) ;
661+
662+ assert ! (
663+ result. is_err( ) ,
664+ "Deserialization should have failed for invalid block number"
665+ ) ;
666+ }
667+ }
0 commit comments