@@ -219,6 +219,45 @@ impl ToHex for [u8] {
219219 }
220220}
221221
222+ /// A struct implementing [`io::Write`] that converts what's written into it
223+ /// in an hex String
224+ ///
225+ /// If you already have the data to be converted in a `Vec<u8>` use [`ToHex`]
226+ /// but if you have an encodable object, by using this you avoid the
227+ /// serialization to `Vec<u8>` by going directly to `String`.
228+ ///
229+ /// Note that to achieve better perfomance than [`ToHex`] the struct must be
230+ /// created with the right `capacity` of the end hex string result so that the
231+ /// inner `String` doesn't re-allocate
232+ pub struct HexWriter ( String ) ;
233+
234+ impl HexWriter {
235+ /// Creates a new [`HexWriter`] specify the `capacity` of the inner `String` that will contain
236+ /// the hex value
237+ pub fn new ( capacity : usize ) -> Self {
238+ HexWriter ( String :: with_capacity ( capacity) )
239+ }
240+
241+ /// Get the hex string result
242+ pub fn result ( self ) -> String {
243+ self . 0
244+ }
245+ }
246+
247+ impl io:: Write for HexWriter {
248+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
249+ use core:: fmt:: Write ;
250+ for ch in buf {
251+ write ! ( self . 0 , "{:02x}" , ch) . expect ( "writing to string" ) ;
252+ }
253+ Ok ( buf. len ( ) )
254+ }
255+
256+ fn flush ( & mut self ) -> io:: Result < ( ) > {
257+ Ok ( ( ) )
258+ }
259+ }
260+
222261#[ cfg( any( test, feature = "std" , feature = "alloc" ) ) ]
223262#[ cfg_attr( docsrs, doc( cfg( any( feature = "std" , feature = "alloc" ) ) ) ) ]
224263impl FromHex for Vec < u8 > {
@@ -276,6 +315,7 @@ mod tests {
276315 use super :: * ;
277316
278317 use core:: fmt;
318+ use std:: io:: Write ;
279319
280320 #[ test]
281321 #[ cfg( any( feature = "std" , feature = "alloc" ) ) ]
@@ -398,5 +438,41 @@ mod tests {
398438 Err ( Error :: InvalidChar ( 194 ) )
399439 ) ;
400440 }
441+
442+
443+ #[ test]
444+ fn hex_writer ( ) {
445+ let vec: Vec < _ > = ( 0u8 ..32 ) . collect ( ) ;
446+ let mut writer = HexWriter :: new ( 64 ) ;
447+ writer. write_all ( & vec[ ..] ) . unwrap ( ) ;
448+ assert_eq ! ( vec. to_hex( ) , writer. result( ) ) ;
449+ }
401450}
402451
452+
453+ #[ cfg( all( test, feature="unstable" ) ) ]
454+ mod benches {
455+ use test:: { Bencher , black_box} ;
456+ use super :: { ToHex , HexWriter } ;
457+ use std:: io:: Write ;
458+ use crate :: { sha256, Hash } ;
459+
460+ #[ bench]
461+ fn bench_to_hex ( bh : & mut Bencher ) {
462+ let hash = sha256:: Hash :: hash ( & [ 0 ; 1 ] ) ;
463+ bh. iter ( || {
464+ black_box ( hash. to_hex ( ) ) ;
465+ } )
466+ }
467+
468+
469+ #[ bench]
470+ fn bench_to_hex_writer ( bh : & mut Bencher ) {
471+ let hash = sha256:: Hash :: hash ( & [ 0 ; 1 ] ) ;
472+ bh. iter ( || {
473+ let mut writer = HexWriter :: new ( 64 ) ;
474+ writer. write_all ( hash. as_inner ( ) ) . unwrap ( ) ;
475+ black_box ( writer. result ( ) ) ;
476+ } )
477+ }
478+ }
0 commit comments