@@ -2,35 +2,38 @@ pub(crate) mod commentwriter;
22pub ( crate ) mod hexdisplaylines;
33
44use crate :: std:: io:: Write ;
5+ use crate :: writer:: clarify:: commentwriter:: RustHexWriter ;
56use crate :: { Encode , Error , SliceWriter } ;
67use crate :: { Length , Result , Tag } ;
78use commentwriter:: { CommentWriter , JavaCommentWriter , XmlCommentWriter } ;
89use hexdisplaylines:: HexDisplayLines ;
910use std:: borrow:: Cow ;
10- use std:: println;
1111use std:: string:: String ;
1212use std:: { boxed:: Box , vec:: Vec } ;
1313
1414use super :: Writer ;
1515
16+ /// Extension trait, auto-implemented on [`Encode`]
1617pub trait EncodeClarifyExt : Encode {
1718 /// Encode this type as pretty-printed hex DER, with comments.
1819 fn to_der_clarify ( & self , flavor : ClarifyFlavor ) -> Result < String > {
19- let outputs = self . to_der_clarify_ignorant ( flavor) ;
20+ let outputs = self . to_der_clarify_err_ignorant ( flavor) ;
2021 // Propagate encode and finish errors
2122 outputs. raw ?;
2223 Ok ( String :: from_utf8 ( outputs. clarify_buf ) . expect ( "clarified output to be utf-8" ) )
2324 }
2425
2526 /// Encode this type as pretty-printed hex DER, with comments.
2627 /// Ignores any errors that occur during [`Encode::encode`].
27- fn to_der_clarify_ignorant ( & self , flavor : ClarifyFlavor ) -> ClarifyOutputs < ' static > {
28+ fn to_der_clarify_err_ignorant ( & self , flavor : ClarifyFlavor ) -> ClarifyOutputs < ' static > {
2829 let len = match self . encoded_len ( ) {
2930 Ok ( len) => len,
3031 Err ( err) => return ClarifyOutputs :: from_err ( err) ,
3132 } ;
3233
33- let mut buf = Vec :: with_capacity ( u32:: from ( len) as usize ) ;
34+ let mut buf: Vec < u8 > = Vec :: new ( ) ;
35+ buf. resize ( u32:: from ( len) as usize , 0u8 ) ;
36+
3437 let mut writer = ClarifySliceWriter :: new ( & mut buf, Vec :: new ( ) , flavor) ;
3538 let result = self . encode ( & mut writer) ;
3639
@@ -104,14 +107,19 @@ impl<'a> ClarifyOutputs<'a> {
104107 // }
105108}
106109
110+ /// Determines how comments will look like
107111#[ derive( Copy , Clone , Debug ) ]
108112pub enum ClarifyFlavor {
113+ /// `01 02 <!-- comment -->`
109114 XmlComments ,
115+ /// `01 02 // comment`
110116 JavaComments ,
117+ /// `"01 02" // comment`
111118 RustHex ,
112119}
113120
114121impl Clarifier {
122+ /// Creates new Clarifier with buffer, that accumulates comments and hex bytes.
115123 pub fn new ( clarify_buf : Vec < u8 > , flavor : ClarifyFlavor ) -> Self {
116124 Self {
117125 clarify_buf,
@@ -123,7 +131,7 @@ impl Clarifier {
123131 comment_writer : match flavor {
124132 ClarifyFlavor :: XmlComments => Box :: new ( XmlCommentWriter :: default ( ) ) ,
125133 ClarifyFlavor :: JavaComments => Box :: new ( JavaCommentWriter :: default ( ) ) ,
126- ClarifyFlavor :: RustHex => todo ! ( ) ,
134+ ClarifyFlavor :: RustHex => Box :: new ( RustHexWriter :: default ( ) ) ,
127135 } ,
128136 }
129137 }
@@ -162,7 +170,9 @@ impl<'a> ClarifySliceWriter<'a> {
162170
163171 /// Finish encoding to the buffer, returning a slice containing the data
164172 /// written to the buffer.
165- pub fn finish ( self ) -> ClarifyOutputs < ' a > {
173+ pub fn finish ( mut self ) -> ClarifyOutputs < ' a > {
174+ self . clarifier . flush_line ( ) ;
175+
166176 ClarifyOutputs {
167177 raw : self . writer . finish ( ) . map ( |raw| Cow :: Borrowed ( raw) ) ,
168178 clarify_buf : self . clarifier . clarify_buf ,
@@ -219,34 +229,48 @@ impl Clarifier {
219229 & INDENT_STR [ ..ilen]
220230 }
221231
232+ /// Writes indent if it is currently enabled
222233 pub fn write_clarify_indent_if_enabled ( & mut self ) {
223234 if self . indent_enabled {
224235 self . write_clarify_indent ( ) ;
225236 }
226237 }
227238
239+ fn flush_line ( & mut self ) {
240+ // if current line ends in space
241+ if self
242+ . clarify_buf
243+ . last ( )
244+ . map ( |last| * last == b' ' )
245+ . unwrap_or_default ( )
246+ {
247+ // remove space
248+ self . clarify_buf . pop ( ) ;
249+ }
250+ // write comment after hex
251+ self . comment_writer . before_new_line ( & mut self . clarify_buf ) ;
252+ }
253+
228254 /// Writes indentation to debug output, for example "\n\t" for depth == 1
229255 pub fn write_clarify_indent ( & mut self ) {
256+ self . flush_line ( ) ;
257+
230258 let indent = self . indent_str ( ) ;
231- {
232- self . comment_writer . before_new_line ( & mut self . clarify_buf ) ;
233- write ! ( & mut self . clarify_buf , " \n {}" , indent ) . unwrap ( ) ;
234- }
259+ write ! ( & mut self . clarify_buf , " \n {}" , indent ) . ok ( ) ;
260+
261+ // write e.g. '"' before hex
262+ self . comment_writer . start_new_line ( & mut self . clarify_buf ) ;
235263 }
236264
237265 /// Writes hex bytes to debug output, for example "30 04 "
238266 pub fn write_clarify_hex ( & mut self , slice : & [ u8 ] ) {
239267 let indent = self . indent_str ( ) ;
240- {
241- write ! ( & mut self . clarify_buf, "{}" , HexDisplayLines ( & slice, indent) ) . unwrap ( ) ;
242- }
268+ write ! ( & mut self . clarify_buf, "{}" , HexDisplayLines ( & slice, indent) ) . ok ( ) ;
243269 }
244270
245271 /// Writes string to debug output, for example a comment "// SEQUENCE"
246272 pub fn write_clarify_str ( & mut self , s : & str ) {
247- {
248- write ! ( & mut self . clarify_buf, "{}" , s) . unwrap ( ) ;
249- }
273+ write ! ( & mut self . clarify_buf, "{}" , s) . unwrap ( ) ;
250274 }
251275 /// Writes string to debug output, for example a comment: `// SEQUENCE: name`
252276 pub fn write_clarify_type_str ( & mut self , start_end : & str , type_name : & str ) {
@@ -291,7 +315,7 @@ impl Clarifier {
291315 match ( writer_pos, last_pos) {
292316 ( Some ( writer_pos) , Some ( last_pos) ) => {
293317 let diff = writer_pos - last_pos;
294- if diff < 16 {
318+ if diff < 15 {
295319 // ignore short runs
296320 return ;
297321 }
@@ -304,9 +328,16 @@ impl Clarifier {
304328 self . write_clarify_type_str ( "end" , type_name. as_ref ( ) ) ;
305329 }
306330
331+ // /// for better tag-length pretty-printing inline
332+ // pub fn clarify_end_tag(&mut self, _tag: &Tag) {
333+ // // just to print a single length byte without indent
334+ // self.indent_enabled = false;
335+ // }
336+
307337 /// for better tag-length pretty-printing inline
308- pub fn clarify_end_tag ( & mut self , _tag : & Tag ) {
309- // just to print a single length byte without indent
338+ pub fn clarify_header_start_tag ( & mut self , _tag : & Tag ) {
339+ self . write_clarify_indent ( ) ;
340+ // just to print header bytes without indent
310341 self . indent_enabled = false ;
311342 }
312343
@@ -318,27 +349,36 @@ impl Clarifier {
318349 // self.indent_enabled = enabled;
319350 // }
320351
352+ /// Writes field name, i.e. field: `public_key`
353+ ///
354+ /// when used on Sequence field:
355+ /// ```text
356+ /// public_key: Option<&'a [u8]>
357+ /// ```
321358 pub fn clarify_field_name ( & mut self , field_name : & str ) {
322359 self . write_clarify_indent ( ) ;
323360 self . write_clarify_type_str ( "field" , field_name) ;
324361 }
325362
326- pub fn clarify_start_value_type < T > ( & mut self ) {
363+ /// Writes e.g. `// type: OctetString`
364+ pub fn clarify_start_value_type < T : ?Sized > ( & mut self ) {
327365 self . clarify_start_value_type_str ( Some ( self . last_position ) , & tynm:: type_name :: < T > ( ) ) ;
328366 }
329- pub fn clarify_end_value_type < T > ( & mut self ) {
367+ /// Writes e.g. `// end: OctetString`
368+ pub fn clarify_end_value_type < T : ?Sized > ( & mut self ) {
330369 self . clarify_end_value_type_str ( Some ( self . last_position ) , & tynm:: type_name :: < T > ( ) ) ;
331370 }
332371
333- // fn clarify_end_length(&mut self, tag: Option<&Tag>, length: Length) {
334- // self.indent_enabled = true;
335- // if let Some(tag) = tag {
336- // self.write_debug_type_str("tag", &format!("{}", tag));
337- // }
338- // if u32::from(length) >= 10 {
339- // self.write_debug_type_str("len", &format!("{}", length));
340- // }
341- // }
372+ /// Writes e.g. `// tag: OCTET STRING len: 17`
373+ pub fn clarify_header_end_length ( & mut self , tag : Option < & Tag > , length : Length ) {
374+ self . indent_enabled = true ;
375+ if let Some ( tag) = tag {
376+ self . write_clarify_type_str ( "tag" , & format ! ( "{}" , tag) ) ;
377+ }
378+ if u32:: from ( length) >= 10 {
379+ self . write_clarify_type_str ( "len" , & format ! ( "{}" , length) ) ;
380+ }
381+ }
342382
343383 // fn clarify_value_quote(&mut self, _type_name: &str, tag_name: &[u8]) {
344384 // //self.write_debug_value_quote(type_name, tag_name);
@@ -349,6 +389,7 @@ impl Clarifier {
349389 // self.write_debug_int(value);
350390 // }
351391
392+ /// Writes pretty-printed `CHOICE name`
352393 pub fn clarify_choice ( & mut self , choice_name : & [ u8 ] ) {
353394 self . write_clarify_indent ( ) ;
354395 if let Ok ( choice_name) = std:: str:: from_utf8 ( choice_name) {
@@ -359,7 +400,6 @@ impl Clarifier {
359400
360401impl < ' a > Writer for ClarifySliceWriter < ' a > {
361402 fn write ( & mut self , slice : & [ u8 ] ) -> Result < ( ) > {
362- println ! ( "writing {slice:?}" ) ;
363403 self . reserve ( slice. len ( ) ) ?. copy_from_slice ( slice) ;
364404 self . clarifier . last_position += slice. len ( ) as u32 ;
365405
@@ -368,6 +408,10 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
368408
369409 Ok ( ( ) )
370410 }
411+
412+ fn clarifier ( & mut self ) -> Option < & mut Clarifier > {
413+ Some ( & mut self . clarifier )
414+ }
371415}
372416
373417/// Strips wrappers, such as `EncodeValueRef`, which is commonly used and is completely transparent
@@ -390,24 +434,3 @@ fn strip_transparent_types(mut type_name: &str) -> Cow<'_, str> {
390434
391435 Cow :: Borrowed ( type_name)
392436}
393-
394- #[ cfg( test) ]
395- pub mod test {
396- use std:: { println, vec:: Vec } ;
397-
398- use crate :: {
399- asn1:: OctetString ,
400- writer:: clarify:: { ClarifyFlavor , EncodeClarifyExt } ,
401- } ;
402-
403- #[ test]
404- fn clarify_simple_octetstring ( ) {
405- let obj = OctetString :: new ( & [ 0xAA , 0xBB , 0xCC ] ) . unwrap ( ) ;
406-
407- let clarified = obj
408- . to_der_clarify ( ClarifyFlavor :: XmlComments )
409- . expect ( "encoded DER" ) ;
410-
411- println ! ( "clarified: {clarified}" ) ;
412- }
413- }
0 commit comments