11use crate :: ber:: BitStringObject ;
22use crate :: ber:: { BerObject , BerObjectContent } ;
3- use alloc:: string:: String ;
3+ use alloc:: string:: { String , ToString } ;
4+ use alloc:: vec;
45use alloc:: vec:: Vec ;
5- use asn1_rs:: Tag ;
6+ use asn1_rs:: { Class , Header , Length , Tag } ;
67use core:: fmt;
78use core:: iter:: FromIterator ;
89use core:: str;
10+ use debug:: HexSlice ;
911
1012use rusticata_macros:: debug;
1113
12- #[ derive( Clone , Debug , PartialEq ) ]
14+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
1315pub enum PrettyPrinterFlag {
16+ Recursive ,
1417 ShowHeader ,
1518}
1619
20+ /// Pretty-print BER object
21+ ///
22+ /// This method is recursive by default. To prevent that, unset the `Recursive` flag.
1723pub struct PrettyBer < ' a > {
1824 obj : & ' a BerObject < ' a > ,
1925 indent : usize ,
@@ -24,23 +30,39 @@ pub struct PrettyBer<'a> {
2430
2531impl < ' a > BerObject < ' a > {
2632 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,
2946 indent,
3047 inc : increment,
31-
32- flags : Vec :: new ( ) ,
48+ flags,
3349 }
3450 }
35- }
3651
37- impl < ' a > PrettyBer < ' a > {
3852 pub fn set_flag ( & mut self , flag : PrettyPrinterFlag ) {
3953 if !self . flags . contains ( & flag) {
4054 self . flags . push ( flag) ;
4155 }
4256 }
4357
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+
4466 pub fn next_indent < ' b > ( & self , obj : & ' b BerObject ) -> PrettyBer < ' b > {
4567 PrettyBer {
4668 obj,
@@ -49,6 +71,32 @@ impl<'a> PrettyBer<'a> {
4971 flags : self . flags . to_vec ( ) ,
5072 }
5173 }
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 ( ( ) )
52100}
53101
54102impl < ' a > fmt:: Debug for PrettyBer < ' a > {
@@ -58,7 +106,8 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
58106 write ! ( f, "{:1$}" , " " , self . indent) ?;
59107 } ;
60108 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, " " ) ?;
62111 } ;
63112 fn print_utf32_string_with_type ( f : & mut fmt:: Formatter , s : & [ u8 ] , ty : & str ) -> fmt:: Result {
64113 let chars: Option < Vec < char > > = s
@@ -72,34 +121,34 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
72121 }
73122 }
74123 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) ) ,
83132 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) ,
98147 BerObjectContent :: UniversalString ( s) => print_utf32_string_with_type ( f, s, "UniversalString" ) ,
99148 BerObjectContent :: Optional ( ref o) => {
100149 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" ) ,
103152 }
104153 }
105154 BerObjectContent :: Tagged ( class, tag, ref obj) => {
@@ -108,23 +157,29 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
108157 if self . indent > 0 {
109158 write ! ( f, "{:1$}" , " " , self . indent) ?;
110159 } ;
111- writeln ! ( f, "}}" ) ?;
160+ write ! ( f, "}}" ) ?;
112161 Ok ( ( ) )
113162 } ,
114163 BerObjectContent :: Set ( ref v) |
115164 BerObjectContent :: Sequence ( ref v) => {
116165 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+ }
125178 Ok ( ( ) )
126179 } ,
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+ } ,
128183 }
129184 }
130185}
0 commit comments