1
1
pub ( crate ) mod commentwriter;
2
2
pub ( crate ) mod hexdisplaylines;
3
3
4
- use crate :: SliceWriter ;
5
4
use crate :: std:: io:: Write ;
5
+ use crate :: { Encode , Error , SliceWriter } ;
6
6
use crate :: { Length , Result , Tag } ;
7
7
use commentwriter:: { CommentWriter , JavaCommentWriter , XmlCommentWriter } ;
8
- use core:: cell:: RefCell ;
9
- use core:: ops:: DerefMut ;
10
8
use hexdisplaylines:: HexDisplayLines ;
11
9
use std:: borrow:: Cow ;
10
+ use std:: println;
12
11
use std:: string:: String ;
13
- use std:: { boxed:: Box , rc :: Rc , vec:: Vec } ;
12
+ use std:: { boxed:: Box , vec:: Vec } ;
14
13
15
14
use super :: Writer ;
16
15
16
+ pub trait EncodeClarifyExt : Encode {
17
+ /// Encode this type as pretty-printed hex DER, with comments.
18
+ fn to_der_clarify ( & self , flavor : ClarifyFlavor ) -> Result < String > {
19
+ let outputs = self . to_der_clarify_ignorant ( flavor) ;
20
+ // Propagate encode and finish errors
21
+ outputs. raw ?;
22
+ Ok ( String :: from_utf8 ( outputs. clarify_buf ) . expect ( "clarified output to be utf-8" ) )
23
+ }
24
+
25
+ /// Encode this type as pretty-printed hex DER, with comments.
26
+ /// Ignores any errors that occur during [`Encode::encode`].
27
+ fn to_der_clarify_ignorant ( & self , flavor : ClarifyFlavor ) -> ClarifyOutputs < ' static > {
28
+ let len = match self . encoded_len ( ) {
29
+ Ok ( len) => len,
30
+ Err ( err) => return ClarifyOutputs :: from_err ( err) ,
31
+ } ;
32
+
33
+ let mut buf = Vec :: with_capacity ( u32:: from ( len) as usize ) ;
34
+ let mut writer = ClarifySliceWriter :: new ( & mut buf, Vec :: new ( ) , flavor) ;
35
+ let result = self . encode ( & mut writer) ;
36
+
37
+ let outputs = writer. finish ( ) ;
38
+ let outputs = ClarifyOutputs {
39
+ // prioritize Encode::encode errors
40
+ raw : result. and ( outputs. raw ) ,
41
+ // but use buffer from finish() (even if encode failed)
42
+ clarify_buf : outputs. clarify_buf ,
43
+ } ;
44
+
45
+ outputs. into_owned ( )
46
+ }
47
+ }
48
+
49
+ impl < T > EncodeClarifyExt for T where T : Encode { }
50
+
17
51
static INDENT_STR : & str =
18
52
"\t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t " ;
19
53
@@ -27,7 +61,7 @@ pub struct ClarifySliceWriter<'a> {
27
61
/// Clarifier that creates HEX with comments
28
62
pub struct Clarifier {
29
63
// Buffer into which debug HEX and comments are written
30
- debug_ref : Rc < RefCell < Vec < u8 > > > ,
64
+ clarify_buf : Vec < u8 > ,
31
65
32
66
// Position in the buffer is used to track how long is the current sub-message
33
67
last_position : u32 ,
@@ -42,35 +76,65 @@ pub struct Clarifier {
42
76
}
43
77
44
78
/// Returned by .finish()
45
- pub struct FinishOutputs < ' a > {
46
- pub raw : Result < & ' a [ u8 ] > ,
47
- //pub debug_ref: Vec<u8>,
79
+ pub struct ClarifyOutputs < ' a > {
80
+ pub raw : Result < Cow < ' a , [ u8 ] > > ,
81
+ pub clarify_buf : Vec < u8 > ,
82
+ }
83
+
84
+ impl < ' a > ClarifyOutputs < ' a > {
85
+ pub fn from_err ( err : Error ) -> ClarifyOutputs < ' static > {
86
+ ClarifyOutputs {
87
+ raw : Err ( err) ,
88
+ clarify_buf : Vec :: new ( ) ,
89
+ }
90
+ }
91
+
92
+ pub fn into_owned ( self ) -> ClarifyOutputs < ' static > {
93
+ ClarifyOutputs {
94
+ raw : self . raw . map ( |raw| Cow :: Owned ( raw. into_owned ( ) ) ) ,
95
+ clarify_buf : self . clarify_buf ,
96
+ }
97
+ }
98
+ // pub fn and(result: Result<Cow<'a, [u8]>>) {
99
+ // ClarifyOutputs {
100
+ // // prioritize Encode::encode errors
101
+ // raw: result.and(outputs.raw),
102
+ // clarify_buf: outputs.clarify_buf,
103
+ // };
104
+ // }
105
+ }
106
+
107
+ #[ derive( Copy , Clone , Debug ) ]
108
+ pub enum ClarifyFlavor {
109
+ XmlComments ,
110
+ JavaComments ,
111
+ RustHex ,
48
112
}
49
113
50
114
impl Clarifier {
51
- pub fn new ( debug_ref : Rc < RefCell < Vec < u8 > > > , comment_xml : bool ) -> Self {
115
+ pub fn new ( clarify_buf : Vec < u8 > , flavor : ClarifyFlavor ) -> Self {
52
116
Self {
53
- debug_ref ,
117
+ clarify_buf ,
54
118
55
119
last_position : 0 ,
56
120
depth : Vec :: new ( ) ,
57
121
58
122
indent_enabled : true ,
59
- comment_writer : if comment_xml {
60
- Box :: new ( XmlCommentWriter :: default ( ) )
61
- } else {
62
- Box :: new ( JavaCommentWriter :: default ( ) )
123
+ comment_writer : match flavor {
124
+ ClarifyFlavor :: XmlComments => Box :: new ( XmlCommentWriter :: default ( ) ) ,
125
+ ClarifyFlavor :: JavaComments => Box :: new ( JavaCommentWriter :: default ( ) ) ,
126
+ ClarifyFlavor :: RustHex => todo ! ( ) ,
63
127
} ,
64
128
}
65
129
}
66
130
}
67
131
68
132
impl < ' a > ClarifySliceWriter < ' a > {
69
133
/// Create a new encoder with the given byte slice as a backing buffer.
70
- pub fn new ( bytes : & ' a mut [ u8 ] , debug_ref : Rc < RefCell < Vec < u8 > > > , comment_xml : bool ) -> Self {
134
+ pub fn new ( bytes : & ' a mut [ u8 ] , clarify_buf : Vec < u8 > , flavor : ClarifyFlavor ) -> Self {
71
135
Self {
72
136
writer : SliceWriter :: new ( bytes) ,
73
- clarifier : Clarifier :: new ( debug_ref , comment_xml ) ,
137
+ clarifier : Clarifier :: new ( clarify_buf , flavor ) ,
74
138
}
75
139
}
76
140
@@ -98,10 +162,10 @@ impl<'a> ClarifySliceWriter<'a> {
98
162
99
163
/// Finish encoding to the buffer, returning a slice containing the data
100
164
/// written to the buffer.
101
- pub fn finish ( self ) -> FinishOutputs < ' a > {
102
- FinishOutputs {
103
- raw : self . writer . finish ( ) ,
104
- //debug_buf : self.debug.expect("debug buf not taken") ,
165
+ pub fn finish ( self ) -> ClarifyOutputs < ' a > {
166
+ ClarifyOutputs {
167
+ raw : self . writer . finish ( ) . map ( |raw| Cow :: Borrowed ( raw ) ) ,
168
+ clarify_buf : self . clarifier . clarify_buf ,
105
169
}
106
170
}
107
171
@@ -164,28 +228,24 @@ impl Clarifier {
164
228
/// Writes indentation to debug output, for example "\n\t" for depth == 1
165
229
pub fn write_clarify_indent ( & mut self ) {
166
230
let indent = self . indent_str ( ) ;
167
- let mut debugbuf = self . debug_ref . borrow_mut ( ) ;
168
231
{
169
- self . comment_writer
170
- . before_new_line ( & mut debugbuf. deref_mut ( ) ) ;
171
- write ! ( debugbuf, "\n {}" , indent) . unwrap ( ) ;
232
+ self . comment_writer . before_new_line ( & mut self . clarify_buf ) ;
233
+ write ! ( & mut self . clarify_buf, "\n {}" , indent) . unwrap ( ) ;
172
234
}
173
235
}
174
236
175
237
/// Writes hex bytes to debug output, for example "30 04 "
176
238
pub fn write_clarify_hex ( & mut self , slice : & [ u8 ] ) {
177
239
let indent = self . indent_str ( ) ;
178
- let mut debugbuf = self . debug_ref . borrow_mut ( ) ;
179
240
{
180
- write ! ( debugbuf , "{}" , HexDisplayLines ( & slice, indent) ) . unwrap ( ) ;
241
+ write ! ( & mut self . clarify_buf , "{}" , HexDisplayLines ( & slice, indent) ) . unwrap ( ) ;
181
242
}
182
243
}
183
244
184
245
/// Writes string to debug output, for example a comment "// SEQUENCE"
185
246
pub fn write_clarify_str ( & mut self , s : & str ) {
186
- let mut debugbuf = self . debug_ref . borrow_mut ( ) ;
187
247
{
188
- write ! ( debugbuf , "{}" , s) . unwrap ( ) ;
248
+ write ! ( & mut self . clarify_buf , "{}" , s) . unwrap ( ) ;
189
249
}
190
250
}
191
251
/// Writes string to debug output, for example a comment: `// SEQUENCE: name`
@@ -299,6 +359,7 @@ impl Clarifier {
299
359
300
360
impl < ' a > Writer for ClarifySliceWriter < ' a > {
301
361
fn write ( & mut self , slice : & [ u8 ] ) -> Result < ( ) > {
362
+ println ! ( "writing {slice:?}" ) ;
302
363
self . reserve ( slice. len ( ) ) ?. copy_from_slice ( slice) ;
303
364
self . clarifier . last_position += slice. len ( ) as u32 ;
304
365
@@ -309,28 +370,44 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
309
370
}
310
371
}
311
372
312
- fn strip_transparent_types ( type_name : & str ) -> Cow < ' _ , str > {
313
- // EncodeValueRef is commonly used and it is completely transparent
314
- let type_name = if let Some ( stripped) = type_name. strip_prefix ( "EncodeValueRef<" ) {
315
- let stripped = stripped. strip_suffix ( ">" ) . unwrap_or ( stripped) ;
316
- stripped
317
- } else {
318
- type_name
319
- } ;
373
+ /// Strips wrappers, such as `EncodeValueRef`, which is commonly used and is completely transparent
374
+ fn strip_transparent_types ( mut type_name : & str ) -> Cow < ' _ , str > {
375
+ let prefixes = [
376
+ "EncodeValueRef<" ,
377
+ "ApplicationRef<" ,
378
+ "ContextSpecificRef<" ,
379
+ "PrivateRef<" ,
380
+ ] ;
381
+
382
+ for prefix in prefixes {
383
+ type_name = if let Some ( stripped) = type_name. strip_prefix ( prefix) {
384
+ let stripped = stripped. strip_suffix ( ">" ) . unwrap_or ( stripped) ;
385
+ stripped
386
+ } else {
387
+ type_name
388
+ } ;
389
+ }
320
390
321
- let type_name = if let Some ( stripped ) = type_name. strip_prefix ( "ApplicationRef<" ) {
322
- let stripped = stripped . strip_suffix ( ">" ) . unwrap_or ( stripped ) ;
323
- stripped
324
- } else {
325
- type_name
326
- } ;
391
+ Cow :: Borrowed ( type_name)
392
+ }
393
+
394
+ # [ cfg ( test ) ]
395
+ pub mod test {
396
+ use std :: { println , vec :: Vec } ;
327
397
328
- let type_name = if let Some ( stripped) = type_name. strip_prefix ( "ContextSpecificRef<" ) {
329
- let stripped = stripped. strip_suffix ( ">" ) . unwrap_or ( stripped) ;
330
- stripped
331
- } else {
332
- type_name
398
+ use crate :: {
399
+ asn1:: OctetString ,
400
+ writer:: clarify:: { ClarifyFlavor , EncodeClarifyExt } ,
333
401
} ;
334
402
335
- Cow :: Borrowed ( type_name)
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
+ }
336
413
}
0 commit comments