1+ // This file is part of Substrate.
2+
3+ // Copyright (C) Parity Technologies (UK) Ltd.
4+ // SPDX-License-Identifier: Apache-2.0
5+
6+ // Licensed under the Apache License, Version 2.0 (the "License");
7+ // you may not use this file except in compliance with the License.
8+ // You may obtain a copy of the License at
9+ //
10+ // http://www.apache.org/licenses/LICENSE-2.0
11+ //
12+ // Unless required by applicable law or agreed to in writing, software
13+ // distributed under the License is distributed on an "AS IS" BASIS,
14+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ // See the License for the specific language governing permissions and
16+ // limitations under the License.
17+
18+ use alloc:: { format, string:: String , vec:: Vec } ;
19+ use alloy_core:: hex;
20+ use serde:: { Deserialize , Deserializer , Serializer } ;
21+
22+ pub trait HexCodec : Sized {
23+ type Error ;
24+ fn to_hex ( & self ) -> String ;
25+ fn from_hex ( s : String ) -> Result < Self , Self :: Error > ;
26+ }
27+
28+ macro_rules! impl_hex_codec {
29+ ( $( $t: ty) ,* ) => {
30+ $(
31+ impl HexCodec for $t {
32+ type Error = core:: num:: ParseIntError ;
33+ fn to_hex( & self ) -> String {
34+ format!( "0x{:x}" , self )
35+ }
36+ fn from_hex( s: String ) -> Result <Self , Self :: Error > {
37+ <$t>:: from_str_radix( s. trim_start_matches( "0x" ) , 16 )
38+ }
39+ }
40+ ) *
41+ } ;
42+ }
43+
44+ impl_hex_codec ! ( u8 , u32 ) ;
45+
46+ impl < const T : usize > HexCodec for [ u8 ; T ] {
47+ type Error = hex:: FromHexError ;
48+ fn to_hex ( & self ) -> String {
49+ format ! ( "0x{}" , hex:: encode( self ) )
50+ }
51+ fn from_hex ( s : String ) -> Result < Self , Self :: Error > {
52+ let data = hex:: decode ( s. trim_start_matches ( "0x" ) ) ?;
53+ data. try_into ( ) . map_err ( |_| hex:: FromHexError :: InvalidStringLength )
54+ }
55+ }
56+
57+ impl HexCodec for Vec < u8 > {
58+ type Error = hex:: FromHexError ;
59+ fn to_hex ( & self ) -> String {
60+ format ! ( "0x{}" , hex:: encode( self ) )
61+ }
62+ fn from_hex ( s : String ) -> Result < Self , Self :: Error > {
63+ hex:: decode ( s. trim_start_matches ( "0x" ) )
64+ }
65+ }
66+
67+ pub fn serialize < S , T > ( value : & T , serializer : S ) -> Result < S :: Ok , S :: Error >
68+ where
69+ S : Serializer ,
70+ T : HexCodec ,
71+ {
72+ let s = value. to_hex ( ) ;
73+ serializer. serialize_str ( & s)
74+ }
75+
76+ pub fn deserialize < ' de , D , T > ( deserializer : D ) -> Result < T , D :: Error >
77+ where
78+ D : Deserializer < ' de > ,
79+ T : HexCodec ,
80+ <T as HexCodec >:: Error : core:: fmt:: Debug ,
81+ {
82+ let s = String :: deserialize ( deserializer) ?;
83+ let value = T :: from_hex ( s) . map_err ( |e| serde:: de:: Error :: custom ( format ! ( "{:?}" , e) ) ) ?;
84+ Ok ( value)
85+ }
0 commit comments