@@ -26,6 +26,8 @@ use std::io;
26
26
use core2:: io;
27
27
28
28
use core:: { fmt, str} ;
29
+ use core:: convert:: Infallible ;
30
+
29
31
use crate :: Hash ;
30
32
31
33
/// Hex decoding error.
@@ -58,15 +60,66 @@ pub trait ToHex {
58
60
}
59
61
60
62
/// Trait for objects that can be deserialized from hex strings.
61
- pub trait FromHex : Sized {
63
+ ///
64
+ /// Implement this trait if the `Error` enum is suitable for returning all your errors, if you need
65
+ /// an additional custom error consider implementing `FromHexRestricted`.
66
+ pub trait FromHex : FromHexRestricted < CustomError = Infallible > + Sized {
62
67
/// Produces an object from a byte iterator.
63
68
fn from_byte_iter < I > ( iter : I ) -> Result < Self , Error >
64
69
where
65
70
I : Iterator < Item = Result < u8 , Error > > + ExactSizeIterator + DoubleEndedIterator ;
66
71
67
72
/// Produces an object from a hex string.
68
73
fn from_hex ( s : & str ) -> Result < Self , Error > {
69
- Self :: from_byte_iter ( HexIterator :: new ( s) ?)
74
+ <Self as FromHex >:: from_byte_iter ( HexIterator :: new ( s) ?)
75
+ }
76
+ }
77
+
78
+ /// Enables users of the library to return a custom error when implementing the `FromHexRestricted` trait.
79
+ pub enum MaybeCustomError < E > {
80
+ /// Wraps the custom error `E`.
81
+ Custom ( E ) ,
82
+ /// Wraps the [`hex::Error`].
83
+ Encoding ( Error ) ,
84
+ }
85
+
86
+ impl < E : fmt:: Display > fmt:: Display for MaybeCustomError < E > {
87
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
88
+ match & * self {
89
+ MaybeCustomError :: Custom ( e) => write ! ( f, "{}" , e) ,
90
+ MaybeCustomError :: Encoding ( e) => write ! ( f, "{}" , e) ,
91
+ }
92
+ }
93
+ }
94
+
95
+ /// Trait for objects that can be deserialized from hex strings.
96
+ ///
97
+ /// Implement this trait if `Error` is not enough and you need an additional custom error. An
98
+ /// implementation of this trait is automatically added for any types that implement `FromHex`.
99
+ pub trait FromHexRestricted : Sized {
100
+ /// The type returned inside of `MaybeCustomError::Custom`.
101
+ type CustomError ;
102
+
103
+ /// Produces an object from a byte iterator.
104
+ fn from_byte_iter < I > ( iter : I ) -> Result < Self , MaybeCustomError < Self :: CustomError > >
105
+ where
106
+ I : Iterator < Item = Result < u8 , Error > > + ExactSizeIterator + DoubleEndedIterator ;
107
+
108
+ /// Produces an object from a hex string.
109
+ fn from_hex ( s : & str ) -> Result < Self , MaybeCustomError < Self :: CustomError > > {
110
+ Self :: from_byte_iter ( HexIterator :: new ( s) . map_err ( |e| MaybeCustomError :: Encoding ( e) ) ?)
111
+ }
112
+ }
113
+
114
+ /// Implements `FromHexRestricted` for types that only error during encoding i.e., no custom error.
115
+ impl < T : FromHex > FromHexRestricted for T {
116
+ type CustomError = Infallible ;
117
+
118
+ fn from_byte_iter < I > ( iter : I ) -> Result < Self , MaybeCustomError < Infallible > >
119
+ where
120
+ I : Iterator < Item = Result < u8 , Error > > + ExactSizeIterator + DoubleEndedIterator
121
+ {
122
+ <T as FromHex >:: from_byte_iter ( iter) . map_err ( |e| MaybeCustomError :: Encoding ( e) )
70
123
}
71
124
}
72
125
@@ -84,11 +137,12 @@ impl<T: Hash> FromHex for T {
84
137
where
85
138
I : Iterator < Item = Result < u8 , Error > > + ExactSizeIterator + DoubleEndedIterator ,
86
139
{
87
- let inner = if Self :: DISPLAY_BACKWARD {
88
- T :: Inner :: from_byte_iter ( iter. rev ( ) ) ?
140
+ let inner;
141
+ if Self :: DISPLAY_BACKWARD {
142
+ inner = <<T as Hash >:: Inner as FromHex >:: from_byte_iter ( iter. rev ( ) ) ?;
89
143
} else {
90
- T :: Inner :: from_byte_iter ( iter) ?
91
- } ;
144
+ inner = << T as Hash > :: Inner as FromHex > :: from_byte_iter ( iter) ?;
145
+ }
92
146
Ok ( Hash :: from_inner ( inner) )
93
147
}
94
148
}
@@ -373,30 +427,23 @@ mod tests {
373
427
let badchar2 = "012Y456789abcdeb" ;
374
428
let badchar3 = "«23456789abcdef" ;
375
429
376
- assert_eq ! (
377
- Vec :: <u8 >:: from_hex( oddlen) ,
378
- Err ( Error :: OddLengthString ( 17 ) )
379
- ) ;
380
- assert_eq ! (
381
- <[ u8 ; 4 ] >:: from_hex( oddlen) ,
382
- Err ( Error :: OddLengthString ( 17 ) )
383
- ) ;
384
- assert_eq ! (
385
- <[ u8 ; 8 ] >:: from_hex( oddlen) ,
386
- Err ( Error :: OddLengthString ( 17 ) )
387
- ) ;
388
- assert_eq ! (
389
- Vec :: <u8 >:: from_hex( badchar1) ,
390
- Err ( Error :: InvalidChar ( b'Z' ) )
391
- ) ;
392
- assert_eq ! (
393
- Vec :: <u8 >:: from_hex( badchar2) ,
394
- Err ( Error :: InvalidChar ( b'Y' ) )
395
- ) ;
396
- assert_eq ! (
397
- Vec :: <u8 >:: from_hex( badchar3) ,
398
- Err ( Error :: InvalidChar ( 194 ) )
399
- ) ;
430
+ let res: Result < Vec < u8 > , Error > = FromHex :: from_hex ( oddlen) ;
431
+ assert_eq ! ( res, Err ( Error :: OddLengthString ( 17 ) ) ) ;
432
+
433
+ let res: Result < [ u8 ; 4 ] , Error > = FromHex :: from_hex ( oddlen) ;
434
+ assert_eq ! ( res, Err ( Error :: OddLengthString ( 17 ) ) ) ;
435
+
436
+ let res: Result < [ u8 ; 8 ] , Error > = FromHex :: from_hex ( oddlen) ;
437
+ assert_eq ! ( res, Err ( Error :: OddLengthString ( 17 ) ) ) ;
438
+
439
+ let res: Result < Vec < u8 > , Error > = FromHex :: from_hex ( badchar1) ;
440
+ assert_eq ! ( res, Err ( Error :: InvalidChar ( b'Z' ) ) ) ;
441
+
442
+ let res: Result < Vec < u8 > , Error > = FromHex :: from_hex ( badchar2) ;
443
+ assert_eq ! ( res, Err ( Error :: InvalidChar ( b'Y' ) ) ) ;
444
+
445
+ let res: Result < Vec < u8 > , Error > = FromHex :: from_hex ( badchar3) ;
446
+ assert_eq ! ( res, Err ( Error :: InvalidChar ( 194 ) ) ) ;
400
447
}
401
448
}
402
449
0 commit comments