@@ -137,7 +137,6 @@ pub use secp256k1_sys as ffi;
137137#[ cfg( all( test, target_arch = "wasm32" ) ) ] extern crate wasm_bindgen_test;
138138#[ cfg( feature = "alloc" ) ] extern crate alloc;
139139
140- use core:: { fmt, ptr, str} ;
141140
142141#[ macro_use]
143142mod macros;
@@ -156,7 +155,7 @@ pub use key::PublicKey;
156155pub use context:: * ;
157156use core:: marker:: PhantomData ;
158157use core:: ops:: Deref ;
159- use core:: mem;
158+ use core:: { mem, fmt , ptr , str } ;
160159use ffi:: { CPtr , types:: AlignedType } ;
161160
162161#[ cfg( feature = "global-context-less-secure" ) ]
@@ -851,6 +850,28 @@ fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
851850 Ok ( idx / 2 )
852851}
853852
853+ /// Utility function used to encode hex into a target u8 buffer. Returns
854+ /// a reference to the target buffer as an str.
855+ // it returns an error if the target buffer isn't big enough
856+ #[ inline]
857+ fn to_hex < ' a > ( src : & [ u8 ] , target : & ' a mut [ u8 ] ) -> Result < & ' a str , ( ) > {
858+ let hex_len = src. len ( ) * 2 ;
859+ if target. len ( ) < hex_len {
860+ return Err ( ( ) ) ;
861+ }
862+ const HEX_TABLE : [ u8 ; 16 ] = * b"0123456789abcdef" ;
863+
864+ let mut i = 0 ;
865+ for & b in src {
866+ target[ i] = HEX_TABLE [ usize:: from ( b >> 4 ) ] ;
867+ target[ i+1 ] = HEX_TABLE [ usize:: from ( b & 0b00001111 ) ] ;
868+ i +=2 ;
869+ }
870+ let result = & target[ ..hex_len] ;
871+ debug_assert ! ( str :: from_utf8( result) . is_ok( ) ) ;
872+ return unsafe { Ok ( str:: from_utf8_unchecked ( result) ) } ;
873+ }
874+
854875
855876#[ cfg( test) ]
856877mod tests {
@@ -859,7 +880,7 @@ mod tests {
859880 use std:: marker:: PhantomData ;
860881
861882 use key:: { SecretKey , PublicKey } ;
862- use super :: from_hex;
883+ use super :: { from_hex, to_hex } ;
863884 use super :: constants;
864885 use super :: { Secp256k1 , Signature , Message } ;
865886 use super :: Error :: { InvalidMessage , IncorrectSignature , InvalidSignature } ;
@@ -1186,6 +1207,32 @@ mod tests {
11861207 assert ! ( Message :: from_slice( & [ 1 ; constants:: MESSAGE_SIZE ] ) . is_ok( ) ) ;
11871208 }
11881209
1210+ #[ test]
1211+ fn test_hex ( ) {
1212+ let mut rng = thread_rng ( ) ;
1213+ const AMOUNT : usize = 1024 ;
1214+ for i in 0 ..AMOUNT {
1215+ // 255 isn't a valid utf8 character.
1216+ let mut hex_buf = [ 255u8 ; AMOUNT * 2 ] ;
1217+ let mut src_buf = [ 0u8 ; AMOUNT ] ;
1218+ let mut result_buf = [ 0u8 ; AMOUNT ] ;
1219+ let src = & mut src_buf[ 0 ..i] ;
1220+ rng. fill_bytes ( src) ;
1221+
1222+ let hex = to_hex ( src, & mut hex_buf) . unwrap ( ) ;
1223+ assert_eq ! ( from_hex( hex, & mut result_buf) . unwrap( ) , i) ;
1224+ assert_eq ! ( src, & result_buf[ ..i] ) ;
1225+ }
1226+
1227+
1228+ assert ! ( to_hex( & [ 1 ; 2 ] , & mut [ 0u8 ; 3 ] ) . is_err( ) ) ;
1229+ assert ! ( to_hex( & [ 1 ; 2 ] , & mut [ 0u8 ; 4 ] ) . is_ok( ) ) ;
1230+ assert ! ( from_hex( "deadbeaf" , & mut [ 0u8 ; 3 ] ) . is_err( ) ) ;
1231+ assert ! ( from_hex( "deadbeaf" , & mut [ 0u8 ; 4 ] ) . is_ok( ) ) ;
1232+ assert ! ( from_hex( "a" , & mut [ 0u8 ; 4 ] ) . is_err( ) ) ;
1233+ assert ! ( from_hex( "ag" , & mut [ 0u8 ; 4 ] ) . is_err( ) ) ;
1234+ }
1235+
11891236 #[ test]
11901237 #[ cfg( not( fuzzing) ) ] // fixed sig vectors can't work with fuzz-sigs
11911238 fn test_low_s ( ) {
0 commit comments