@@ -255,6 +255,7 @@ enum Error {
255255 TooManyDecimals ( usize , usize ) ,
256256 InvalidFixedBytesLength ( usize ) ,
257257 FixedArrayLengthMismatch ( usize , usize ) ,
258+ EmptyHexStringWithoutPrefix ,
258259}
259260
260261#[ cfg( feature = "std" ) ]
@@ -284,6 +285,7 @@ impl fmt::Display for Error {
284285 f,
285286 "fixed array length mismatch: expected {expected} elements, got {actual}"
286287 ) ,
288+ Self :: EmptyHexStringWithoutPrefix => f. write_str ( "expected hex digits or the `0x` prefix for an empty hex string" ) ,
287289 }
288290 }
289291}
@@ -474,27 +476,35 @@ fn fixed_bytes<'i>(len: usize) -> impl Parser<&'i str, Word, ContextError> {
474476
475477#[ inline]
476478fn address ( input : & mut & str ) -> PResult < Address > {
477- trace ( "address" , fixed_bytes_inner ) . parse_next ( input ) . map ( Address :: from )
479+ trace ( "address" , hex_str . try_map ( hex :: FromHex :: from_hex ) ) . parse_next ( input )
478480}
479481
480482#[ inline]
481483fn function ( input : & mut & str ) -> PResult < Function > {
482- trace ( "function" , fixed_bytes_inner ) . parse_next ( input ) . map ( Function :: from )
484+ trace ( "function" , hex_str . try_map ( hex :: FromHex :: from_hex ) ) . parse_next ( input )
483485}
484486
485487#[ inline]
486488fn bytes ( input : & mut & str ) -> PResult < Vec < u8 > > {
487489 trace ( "bytes" , hex_str. try_map ( hex:: decode) ) . parse_next ( input)
488490}
489491
490- #[ inline]
491- fn fixed_bytes_inner < const N : usize > ( input : & mut & str ) -> PResult < FixedBytes < N > > {
492- hex_str. try_map ( |s| hex:: decode_to_array ( s) . map ( Into :: into) ) . parse_next ( input)
493- }
494-
495492#[ inline]
496493fn hex_str < ' i > ( input : & mut & ' i str ) -> PResult < & ' i str > {
497- trace ( "hex_str" , preceded ( opt ( "0x" ) , hex_digit0) ) . parse_next ( input)
494+ trace ( "hex_str" , |input : & mut & ' i str | {
495+ // Allow empty `bytes` only with a prefix.
496+ let has_prefix = opt ( "0x" ) . parse_next ( input) ?. is_some ( ) ;
497+ let s = hex_digit0 ( input) ?;
498+ if !has_prefix && s. is_empty ( ) {
499+ return Err ( ErrMode :: from_external_error (
500+ input,
501+ ErrorKind :: Verify ,
502+ Error :: EmptyHexStringWithoutPrefix ,
503+ ) ) ;
504+ }
505+ Ok ( s)
506+ } )
507+ . parse_next ( input)
498508}
499509
500510fn hex_error ( input : & & str , e : FromHexError ) -> ErrMode < ContextError > {
@@ -849,7 +859,7 @@ mod tests {
849859 ) ;
850860
851861 let e = DynSolType :: FixedBytes ( 1 ) . coerce_str ( "" ) . unwrap_err ( ) ;
852- assert_error_contains ( & e, "Invalid string length" ) ;
862+ assert_error_contains ( & e, & Error :: EmptyHexStringWithoutPrefix . to_string ( ) ) ;
853863 let e = DynSolType :: FixedBytes ( 1 ) . coerce_str ( "0" ) . unwrap_err ( ) ;
854864 assert_error_contains ( & e, "Odd number of digits" ) ;
855865 let e = DynSolType :: FixedBytes ( 1 ) . coerce_str ( "0x" ) . unwrap_err ( ) ;
@@ -919,7 +929,9 @@ mod tests {
919929
920930 #[ test]
921931 fn coerce_bytes ( ) {
922- assert_eq ! ( DynSolType :: Bytes . coerce_str( "" ) . unwrap( ) , DynSolValue :: Bytes ( vec![ ] ) ) ;
932+ let e = DynSolType :: Bytes . coerce_str ( "" ) . unwrap_err ( ) ;
933+ assert_error_contains ( & e, & Error :: EmptyHexStringWithoutPrefix . to_string ( ) ) ;
934+
923935 assert_eq ! ( DynSolType :: Bytes . coerce_str( "0x" ) . unwrap( ) , DynSolValue :: Bytes ( vec![ ] ) ) ;
924936 assert ! ( DynSolType :: Bytes . coerce_str( "0x0" ) . is_err( ) ) ;
925937 assert ! ( DynSolType :: Bytes . coerce_str( "0" ) . is_err( ) ) ;
@@ -1038,6 +1050,24 @@ mod tests {
10381050 assert_eq ! ( arr. coerce_str( "[\" \" , \" \" ]" ) . unwrap( ) , mk_arr( & [ "" , "" ] ) ) ;
10391051 }
10401052
1053+ #[ test]
1054+ fn coerce_array_of_bytes_and_strings ( ) {
1055+ let ty = DynSolType :: Array ( Box :: new ( DynSolType :: Bytes ) ) ;
1056+ assert_eq ! ( ty. coerce_str( "[]" ) , Ok ( DynSolValue :: Array ( vec![ ] ) ) ) ;
1057+ assert_eq ! ( ty. coerce_str( "[0x]" ) , Ok ( DynSolValue :: Array ( vec![ DynSolValue :: Bytes ( vec![ ] ) ] ) ) ) ;
1058+
1059+ let ty = DynSolType :: Array ( Box :: new ( DynSolType :: String ) ) ;
1060+ assert_eq ! ( ty. coerce_str( "[]" ) , Ok ( DynSolValue :: Array ( vec![ ] ) ) ) ;
1061+ assert_eq ! (
1062+ ty. coerce_str( "[\" \" ]" ) ,
1063+ Ok ( DynSolValue :: Array ( vec![ DynSolValue :: String ( String :: new( ) ) ] ) )
1064+ ) ;
1065+ assert_eq ! (
1066+ ty. coerce_str( "[0x]" ) ,
1067+ Ok ( DynSolValue :: Array ( vec![ DynSolValue :: String ( "0x" . into( ) ) ] ) )
1068+ ) ;
1069+ }
1070+
10411071 #[ test]
10421072 fn coerce_empty_array ( ) {
10431073 assert_eq ! (
0 commit comments