@@ -2,35 +2,38 @@ pub(crate) mod commentwriter;
2
2
pub ( crate ) mod hexdisplaylines;
3
3
4
4
use crate :: std:: io:: Write ;
5
+ use crate :: writer:: clarify:: commentwriter:: RustHexWriter ;
5
6
use crate :: { Encode , Error , SliceWriter } ;
6
7
use crate :: { Length , Result , Tag } ;
7
8
use commentwriter:: { CommentWriter , JavaCommentWriter , XmlCommentWriter } ;
8
9
use hexdisplaylines:: HexDisplayLines ;
9
10
use std:: borrow:: Cow ;
10
- use std:: println;
11
11
use std:: string:: String ;
12
12
use std:: { boxed:: Box , vec:: Vec } ;
13
13
14
14
use super :: Writer ;
15
15
16
+ /// Extension trait, auto-implemented on [`Encode`]
16
17
pub trait EncodeClarifyExt : Encode {
17
18
/// Encode this type as pretty-printed hex DER, with comments.
18
19
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) ;
20
21
// Propagate encode and finish errors
21
22
outputs. raw ?;
22
23
Ok ( String :: from_utf8 ( outputs. clarify_buf ) . expect ( "clarified output to be utf-8" ) )
23
24
}
24
25
25
26
/// Encode this type as pretty-printed hex DER, with comments.
26
27
/// 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 > {
28
29
let len = match self . encoded_len ( ) {
29
30
Ok ( len) => len,
30
31
Err ( err) => return ClarifyOutputs :: from_err ( err) ,
31
32
} ;
32
33
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
+
34
37
let mut writer = ClarifySliceWriter :: new ( & mut buf, Vec :: new ( ) , flavor) ;
35
38
let result = self . encode ( & mut writer) ;
36
39
@@ -104,14 +107,19 @@ impl<'a> ClarifyOutputs<'a> {
104
107
// }
105
108
}
106
109
110
+ /// Determines how comments will look like
107
111
#[ derive( Copy , Clone , Debug ) ]
108
112
pub enum ClarifyFlavor {
113
+ /// `01 02 <!-- comment -->`
109
114
XmlComments ,
115
+ /// `01 02 // comment`
110
116
JavaComments ,
117
+ /// `"01 02" // comment`
111
118
RustHex ,
112
119
}
113
120
114
121
impl Clarifier {
122
+ /// Creates new Clarifier with buffer, that accumulates comments and hex bytes.
115
123
pub fn new ( clarify_buf : Vec < u8 > , flavor : ClarifyFlavor ) -> Self {
116
124
Self {
117
125
clarify_buf,
@@ -123,7 +131,7 @@ impl Clarifier {
123
131
comment_writer : match flavor {
124
132
ClarifyFlavor :: XmlComments => Box :: new ( XmlCommentWriter :: default ( ) ) ,
125
133
ClarifyFlavor :: JavaComments => Box :: new ( JavaCommentWriter :: default ( ) ) ,
126
- ClarifyFlavor :: RustHex => todo ! ( ) ,
134
+ ClarifyFlavor :: RustHex => Box :: new ( RustHexWriter :: default ( ) ) ,
127
135
} ,
128
136
}
129
137
}
@@ -162,7 +170,9 @@ impl<'a> ClarifySliceWriter<'a> {
162
170
163
171
/// Finish encoding to the buffer, returning a slice containing the data
164
172
/// 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
+
166
176
ClarifyOutputs {
167
177
raw : self . writer . finish ( ) . map ( |raw| Cow :: Borrowed ( raw) ) ,
168
178
clarify_buf : self . clarifier . clarify_buf ,
@@ -219,34 +229,48 @@ impl Clarifier {
219
229
& INDENT_STR [ ..ilen]
220
230
}
221
231
232
+ /// Writes indent if it is currently enabled
222
233
pub fn write_clarify_indent_if_enabled ( & mut self ) {
223
234
if self . indent_enabled {
224
235
self . write_clarify_indent ( ) ;
225
236
}
226
237
}
227
238
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
+
228
254
/// Writes indentation to debug output, for example "\n\t" for depth == 1
229
255
pub fn write_clarify_indent ( & mut self ) {
256
+ self . flush_line ( ) ;
257
+
230
258
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 ) ;
235
263
}
236
264
237
265
/// Writes hex bytes to debug output, for example "30 04 "
238
266
pub fn write_clarify_hex ( & mut self , slice : & [ u8 ] ) {
239
267
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 ( ) ;
243
269
}
244
270
245
271
/// Writes string to debug output, for example a comment "// SEQUENCE"
246
272
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 ( ) ;
250
274
}
251
275
/// Writes string to debug output, for example a comment: `// SEQUENCE: name`
252
276
pub fn write_clarify_type_str ( & mut self , start_end : & str , type_name : & str ) {
@@ -291,7 +315,7 @@ impl Clarifier {
291
315
match ( writer_pos, last_pos) {
292
316
( Some ( writer_pos) , Some ( last_pos) ) => {
293
317
let diff = writer_pos - last_pos;
294
- if diff < 16 {
318
+ if diff < 15 {
295
319
// ignore short runs
296
320
return ;
297
321
}
@@ -304,9 +328,16 @@ impl Clarifier {
304
328
self . write_clarify_type_str ( "end" , type_name. as_ref ( ) ) ;
305
329
}
306
330
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
+
307
337
/// 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
310
341
self . indent_enabled = false ;
311
342
}
312
343
@@ -318,27 +349,36 @@ impl Clarifier {
318
349
// self.indent_enabled = enabled;
319
350
// }
320
351
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
+ /// ```
321
358
pub fn clarify_field_name ( & mut self , field_name : & str ) {
322
359
self . write_clarify_indent ( ) ;
323
360
self . write_clarify_type_str ( "field" , field_name) ;
324
361
}
325
362
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 ) {
327
365
self . clarify_start_value_type_str ( Some ( self . last_position ) , & tynm:: type_name :: < T > ( ) ) ;
328
366
}
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 ) {
330
369
self . clarify_end_value_type_str ( Some ( self . last_position ) , & tynm:: type_name :: < T > ( ) ) ;
331
370
}
332
371
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
+ }
342
382
343
383
// fn clarify_value_quote(&mut self, _type_name: &str, tag_name: &[u8]) {
344
384
// //self.write_debug_value_quote(type_name, tag_name);
@@ -349,6 +389,7 @@ impl Clarifier {
349
389
// self.write_debug_int(value);
350
390
// }
351
391
392
+ /// Writes pretty-printed `CHOICE name`
352
393
pub fn clarify_choice ( & mut self , choice_name : & [ u8 ] ) {
353
394
self . write_clarify_indent ( ) ;
354
395
if let Ok ( choice_name) = std:: str:: from_utf8 ( choice_name) {
@@ -359,7 +400,6 @@ impl Clarifier {
359
400
360
401
impl < ' a > Writer for ClarifySliceWriter < ' a > {
361
402
fn write ( & mut self , slice : & [ u8 ] ) -> Result < ( ) > {
362
- println ! ( "writing {slice:?}" ) ;
363
403
self . reserve ( slice. len ( ) ) ?. copy_from_slice ( slice) ;
364
404
self . clarifier . last_position += slice. len ( ) as u32 ;
365
405
@@ -368,6 +408,10 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
368
408
369
409
Ok ( ( ) )
370
410
}
411
+
412
+ fn clarifier ( & mut self ) -> Option < & mut Clarifier > {
413
+ Some ( & mut self . clarifier )
414
+ }
371
415
}
372
416
373
417
/// 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> {
390
434
391
435
Cow :: Borrowed ( type_name)
392
436
}
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