1
1
use crate :: ber:: BitStringObject ;
2
2
use crate :: ber:: { BerObject , BerObjectContent } ;
3
- use alloc:: string:: String ;
3
+ use alloc:: string:: { String , ToString } ;
4
+ use alloc:: vec;
4
5
use alloc:: vec:: Vec ;
5
- use asn1_rs:: Tag ;
6
+ use asn1_rs:: { Class , Header , Length , Tag } ;
6
7
use core:: fmt;
7
8
use core:: iter:: FromIterator ;
8
9
use core:: str;
10
+ use debug:: HexSlice ;
9
11
10
12
use rusticata_macros:: debug;
11
13
12
- #[ derive( Clone , Debug , PartialEq ) ]
14
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
13
15
pub enum PrettyPrinterFlag {
16
+ Recursive ,
14
17
ShowHeader ,
15
18
}
16
19
20
+ /// Pretty-print BER object
21
+ ///
22
+ /// This method is recursive by default. To prevent that, unset the `Recursive` flag.
17
23
pub struct PrettyBer < ' a > {
18
24
obj : & ' a BerObject < ' a > ,
19
25
indent : usize ,
@@ -24,23 +30,39 @@ pub struct PrettyBer<'a> {
24
30
25
31
impl < ' a > BerObject < ' a > {
26
32
pub fn as_pretty ( & ' a self , indent : usize , increment : usize ) -> PrettyBer < ' a > {
27
- PrettyBer {
28
- obj : self ,
33
+ PrettyBer :: new ( self , vec ! [ PrettyPrinterFlag :: Recursive ] , indent, increment)
34
+ }
35
+ }
36
+
37
+ impl < ' a > PrettyBer < ' a > {
38
+ pub const fn new (
39
+ obj : & ' a BerObject < ' a > ,
40
+ flags : Vec < PrettyPrinterFlag > ,
41
+ indent : usize ,
42
+ increment : usize ,
43
+ ) -> Self {
44
+ Self {
45
+ obj,
29
46
indent,
30
47
inc : increment,
31
-
32
- flags : Vec :: new ( ) ,
48
+ flags,
33
49
}
34
50
}
35
- }
36
51
37
- impl < ' a > PrettyBer < ' a > {
38
52
pub fn set_flag ( & mut self , flag : PrettyPrinterFlag ) {
39
53
if !self . flags . contains ( & flag) {
40
54
self . flags . push ( flag) ;
41
55
}
42
56
}
43
57
58
+ pub fn unset_flag ( & mut self , flag : PrettyPrinterFlag ) {
59
+ self . flags . retain ( |& f| f != flag) ;
60
+ }
61
+
62
+ pub fn is_flag_set ( & self , flag : PrettyPrinterFlag ) -> bool {
63
+ self . flags . contains ( & flag)
64
+ }
65
+
44
66
pub fn next_indent < ' b > ( & self , obj : & ' b BerObject ) -> PrettyBer < ' b > {
45
67
PrettyBer {
46
68
obj,
@@ -49,6 +71,32 @@ impl<'a> PrettyBer<'a> {
49
71
flags : self . flags . to_vec ( ) ,
50
72
}
51
73
}
74
+
75
+ #[ inline]
76
+ fn is_recursive ( & self ) -> bool {
77
+ self . is_flag_set ( PrettyPrinterFlag :: Recursive )
78
+ }
79
+ }
80
+
81
+ fn dbg_header ( header : & Header , f : & mut fmt:: Formatter ) -> fmt:: Result {
82
+ let s_constructed = if header. is_constructed ( ) { "+" } else { "" } ;
83
+ let l = match header. length ( ) {
84
+ Length :: Definite ( sz) => sz. to_string ( ) ,
85
+ Length :: Indefinite => "Indefinite" . to_string ( ) ,
86
+ } ;
87
+ match header. class ( ) {
88
+ Class :: Universal => {
89
+ write ! ( f, "[{}]{} {}" , header. tag( ) , s_constructed, l) ?;
90
+ }
91
+ Class :: ContextSpecific => {
92
+ write ! ( f, "[{}]{} {}" , header. tag( ) . 0 , s_constructed, l) ?;
93
+ }
94
+
95
+ class => {
96
+ write ! ( f, "[{} {}]{} {}" , class, header. tag( ) . 0 , s_constructed, l) ?;
97
+ }
98
+ }
99
+ Ok ( ( ) )
52
100
}
53
101
54
102
impl < ' a > fmt:: Debug for PrettyBer < ' a > {
@@ -58,7 +106,8 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
58
106
write ! ( f, "{:1$}" , " " , self . indent) ?;
59
107
} ;
60
108
if self . flags . contains ( & PrettyPrinterFlag :: ShowHeader ) {
61
- write ! ( f, "[c:{:?}, s:{}, t:{}] " , self . obj. header. class( ) , self . obj. header. constructed( ) , self . obj. header. tag( ) ) ?;
109
+ dbg_header ( & self . obj . header , f) ?;
110
+ write ! ( f, " " ) ?;
62
111
} ;
63
112
fn print_utf32_string_with_type ( f : & mut fmt:: Formatter , s : & [ u8 ] , ty : & str ) -> fmt:: Result {
64
113
let chars: Option < Vec < char > > = s
@@ -72,34 +121,34 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
72
121
}
73
122
}
74
123
match self . obj . content {
75
- BerObjectContent :: EndOfContent => writeln ! ( f, "EndOfContent" ) ,
76
- BerObjectContent :: Boolean ( b) => writeln ! ( f, "Boolean({:?})" , b) ,
77
- BerObjectContent :: Integer ( i) => writeln ! ( f, "Integer({:?})" , debug :: HexSlice ( i) ) ,
78
- BerObjectContent :: Enum ( i) => writeln ! ( f, "Enum({})" , i) ,
79
- BerObjectContent :: OID ( ref v) => writeln ! ( f, "OID({:?})" , v) ,
80
- BerObjectContent :: RelativeOID ( ref v) => writeln ! ( f, "RelativeOID({:?})" , v) ,
81
- BerObjectContent :: Null => writeln ! ( f, "Null" ) ,
82
- BerObjectContent :: OctetString ( v) => writeln ! ( f, "OctetString({:?})" , debug :: HexSlice ( v) ) ,
124
+ BerObjectContent :: EndOfContent => write ! ( f, "EndOfContent" ) ,
125
+ BerObjectContent :: Boolean ( b) => write ! ( f, "Boolean({:?})" , b) ,
126
+ BerObjectContent :: Integer ( i) => write ! ( f, "Integer({:?})" , HexSlice ( i) ) ,
127
+ BerObjectContent :: Enum ( i) => write ! ( f, "Enum({})" , i) ,
128
+ BerObjectContent :: OID ( ref v) => write ! ( f, "OID({:?})" , v) ,
129
+ BerObjectContent :: RelativeOID ( ref v) => write ! ( f, "RelativeOID({:?})" , v) ,
130
+ BerObjectContent :: Null => write ! ( f, "Null" ) ,
131
+ BerObjectContent :: OctetString ( v) => write ! ( f, "OctetString({:?})" , HexSlice ( v) ) ,
83
132
BerObjectContent :: BitString ( u, BitStringObject { data : v} )
84
- => writeln ! ( f, "BitString({},{:?})" , u, debug :: HexSlice ( v) ) ,
85
- BerObjectContent :: GeneralizedTime ( ref time) => writeln ! ( f, "GeneralizedTime(\" {}\" )" , time) ,
86
- BerObjectContent :: UTCTime ( ref time) => writeln ! ( f, "UTCTime(\" {}\" )" , time) ,
87
- BerObjectContent :: VisibleString ( s) => writeln ! ( f, "VisibleString(\" {}\" )" , s) ,
88
- BerObjectContent :: GeneralString ( s) => writeln ! ( f, "GeneralString(\" {}\" )" , s) ,
89
- BerObjectContent :: GraphicString ( s) => writeln ! ( f, "GraphicString(\" {}\" )" , s) ,
90
- BerObjectContent :: PrintableString ( s) => writeln ! ( f, "PrintableString(\" {}\" )" , s) ,
91
- BerObjectContent :: NumericString ( s) => writeln ! ( f, "NumericString(\" {}\" )" , s) ,
92
- BerObjectContent :: UTF8String ( s) => writeln ! ( f, "UTF8String(\" {}\" )" , s) ,
93
- BerObjectContent :: IA5String ( s) => writeln ! ( f, "IA5String(\" {}\" )" , s) ,
94
- BerObjectContent :: T61String ( s) => writeln ! ( f, "T61String({})" , s) ,
95
- BerObjectContent :: VideotexString ( s) => writeln ! ( f, "VideotexString({})" , s) ,
96
- BerObjectContent :: ObjectDescriptor ( s) => writeln ! ( f, "ObjectDescriptor(\" {}\" )" , s) ,
97
- BerObjectContent :: BmpString ( s) => writeln ! ( f, "BmpString(\" {}\" )" , s) ,
133
+ => write ! ( f, "BitString({},{:?})" , u, HexSlice ( v) ) ,
134
+ BerObjectContent :: GeneralizedTime ( ref time) => write ! ( f, "GeneralizedTime(\" {}\" )" , time) ,
135
+ BerObjectContent :: UTCTime ( ref time) => write ! ( f, "UTCTime(\" {}\" )" , time) ,
136
+ BerObjectContent :: VisibleString ( s) => write ! ( f, "VisibleString(\" {}\" )" , s) ,
137
+ BerObjectContent :: GeneralString ( s) => write ! ( f, "GeneralString(\" {}\" )" , s) ,
138
+ BerObjectContent :: GraphicString ( s) => write ! ( f, "GraphicString(\" {}\" )" , s) ,
139
+ BerObjectContent :: PrintableString ( s) => write ! ( f, "PrintableString(\" {}\" )" , s) ,
140
+ BerObjectContent :: NumericString ( s) => write ! ( f, "NumericString(\" {}\" )" , s) ,
141
+ BerObjectContent :: UTF8String ( s) => write ! ( f, "UTF8String(\" {}\" )" , s) ,
142
+ BerObjectContent :: IA5String ( s) => write ! ( f, "IA5String(\" {}\" )" , s) ,
143
+ BerObjectContent :: T61String ( s) => write ! ( f, "T61String({})" , s) ,
144
+ BerObjectContent :: VideotexString ( s) => write ! ( f, "VideotexString({})" , s) ,
145
+ BerObjectContent :: ObjectDescriptor ( s) => write ! ( f, "ObjectDescriptor(\" {}\" )" , s) ,
146
+ BerObjectContent :: BmpString ( s) => write ! ( f, "BmpString(\" {}\" )" , s) ,
98
147
BerObjectContent :: UniversalString ( s) => print_utf32_string_with_type ( f, s, "UniversalString" ) ,
99
148
BerObjectContent :: Optional ( ref o) => {
100
149
match o {
101
- Some ( obj) => writeln ! ( f, "OPTION {:?}" , obj) ,
102
- None => writeln ! ( f, "NONE" ) ,
150
+ Some ( obj) => write ! ( f, "OPTION {:?}" , obj) ,
151
+ None => write ! ( f, "NONE" ) ,
103
152
}
104
153
}
105
154
BerObjectContent :: Tagged ( class, tag, ref obj) => {
@@ -108,23 +157,29 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
108
157
if self . indent > 0 {
109
158
write ! ( f, "{:1$}" , " " , self . indent) ?;
110
159
} ;
111
- writeln ! ( f, "}}" ) ?;
160
+ write ! ( f, "}}" ) ?;
112
161
Ok ( ( ) )
113
162
} ,
114
163
BerObjectContent :: Set ( ref v) |
115
164
BerObjectContent :: Sequence ( ref v) => {
116
165
let ty = if self . obj . header . tag ( ) == Tag :: Sequence { "Sequence" } else { "Set" } ;
117
- writeln ! ( f, "{}[" , ty) ?;
118
- for o in v {
119
- write ! ( f, "{:?}" , self . next_indent( o) ) ?;
120
- } ;
121
- if self . indent > 0 {
122
- write ! ( f, "{:1$}" , " " , self . indent) ?;
123
- } ;
124
- writeln ! ( f, "]" ) ?;
166
+ if self . is_recursive ( ) {
167
+ writeln ! ( f, "{}[" , ty) ?;
168
+ for o in v {
169
+ write ! ( f, "{:?}" , self . next_indent( o) ) ?;
170
+ } ;
171
+ if self . indent > 0 {
172
+ write ! ( f, "{:1$}" , " " , self . indent) ?;
173
+ } ;
174
+ write ! ( f, "]" ) ?;
175
+ } else {
176
+ write ! ( f, "{}" , ty) ?;
177
+ }
125
178
Ok ( ( ) )
126
179
} ,
127
- BerObjectContent :: Unknown ( ref any) => writeln ! ( f, "Unknown([{} {}] {:x?})" , any. class( ) , any. tag( ) . 0 , debug:: HexSlice ( any. data) ) ,
180
+ BerObjectContent :: Unknown ( ref any) => {
181
+ write ! ( f, "Unknown {:x?}" , HexSlice ( any. data) )
182
+ } ,
128
183
}
129
184
}
130
185
}
0 commit comments