11pub ( crate ) mod commentwriter;
22pub ( crate ) mod hexdisplaylines;
33
4- use crate :: SliceWriter ;
54use crate :: std:: io:: Write ;
5+ use crate :: { Encode , Error , SliceWriter } ;
66use crate :: { Length , Result , Tag } ;
77use commentwriter:: { CommentWriter , JavaCommentWriter , XmlCommentWriter } ;
8- use core:: cell:: RefCell ;
9- use core:: ops:: DerefMut ;
108use hexdisplaylines:: HexDisplayLines ;
119use std:: borrow:: Cow ;
10+ use std:: println;
1211use std:: string:: String ;
13- use std:: { boxed:: Box , rc :: Rc , vec:: Vec } ;
12+ use std:: { boxed:: Box , vec:: Vec } ;
1413
1514use super :: Writer ;
1615
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+
1751static INDENT_STR : & str =
1852 "\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 " ;
1953
@@ -27,7 +61,7 @@ pub struct ClarifySliceWriter<'a> {
2761/// Clarifier that creates HEX with comments
2862pub struct Clarifier {
2963 // Buffer into which debug HEX and comments are written
30- debug_ref : Rc < RefCell < Vec < u8 > > > ,
64+ clarify_buf : Vec < u8 > ,
3165
3266 // Position in the buffer is used to track how long is the current sub-message
3367 last_position : u32 ,
@@ -42,35 +76,65 @@ pub struct Clarifier {
4276}
4377
4478/// 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 ,
48112}
49113
50114impl 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 {
52116 Self {
53- debug_ref ,
117+ clarify_buf ,
54118
55119 last_position : 0 ,
56120 depth : Vec :: new ( ) ,
57121
58122 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 ! ( ) ,
63127 } ,
64128 }
65129 }
66130}
67131
68132impl < ' a > ClarifySliceWriter < ' a > {
69133 /// 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 {
71135 Self {
72136 writer : SliceWriter :: new ( bytes) ,
73- clarifier : Clarifier :: new ( debug_ref , comment_xml ) ,
137+ clarifier : Clarifier :: new ( clarify_buf , flavor ) ,
74138 }
75139 }
76140
@@ -98,10 +162,10 @@ impl<'a> ClarifySliceWriter<'a> {
98162
99163 /// Finish encoding to the buffer, returning a slice containing the data
100164 /// 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 ,
105169 }
106170 }
107171
@@ -164,28 +228,24 @@ impl Clarifier {
164228 /// Writes indentation to debug output, for example "\n\t" for depth == 1
165229 pub fn write_clarify_indent ( & mut self ) {
166230 let indent = self . indent_str ( ) ;
167- let mut debugbuf = self . debug_ref . borrow_mut ( ) ;
168231 {
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 ( ) ;
172234 }
173235 }
174236
175237 /// Writes hex bytes to debug output, for example "30 04 "
176238 pub fn write_clarify_hex ( & mut self , slice : & [ u8 ] ) {
177239 let indent = self . indent_str ( ) ;
178- let mut debugbuf = self . debug_ref . borrow_mut ( ) ;
179240 {
180- write ! ( debugbuf , "{}" , HexDisplayLines ( & slice, indent) ) . unwrap ( ) ;
241+ write ! ( & mut self . clarify_buf , "{}" , HexDisplayLines ( & slice, indent) ) . unwrap ( ) ;
181242 }
182243 }
183244
184245 /// Writes string to debug output, for example a comment "// SEQUENCE"
185246 pub fn write_clarify_str ( & mut self , s : & str ) {
186- let mut debugbuf = self . debug_ref . borrow_mut ( ) ;
187247 {
188- write ! ( debugbuf , "{}" , s) . unwrap ( ) ;
248+ write ! ( & mut self . clarify_buf , "{}" , s) . unwrap ( ) ;
189249 }
190250 }
191251 /// Writes string to debug output, for example a comment: `// SEQUENCE: name`
@@ -299,6 +359,7 @@ impl Clarifier {
299359
300360impl < ' a > Writer for ClarifySliceWriter < ' a > {
301361 fn write ( & mut self , slice : & [ u8 ] ) -> Result < ( ) > {
362+ println ! ( "writing {slice:?}" ) ;
302363 self . reserve ( slice. len ( ) ) ?. copy_from_slice ( slice) ;
303364 self . clarifier . last_position += slice. len ( ) as u32 ;
304365
@@ -309,28 +370,44 @@ impl<'a> Writer for ClarifySliceWriter<'a> {
309370 }
310371}
311372
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+ }
320390
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 } ;
327397
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 } ,
333401 } ;
334402
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+ }
336413}
0 commit comments