@@ -10,8 +10,9 @@ use crate::public_key::*;
1010
1111use asn1_rs:: num_bigint:: BigUint ;
1212use asn1_rs:: {
13- Alias , Any , BerError , BitString , DerParser , Enumerated , FromDer , Header , Input , Integer ,
14- OptTaggedExplicit , Sequence , Tag , Tagged ,
13+ Alias , Any , BerError , BitString , BmpString , Choice , DerParser , Enumerated , FromDer , Header ,
14+ Input , Integer , OptTaggedExplicit , PrintableString , Sequence , Tag , Tagged , TeletexString ,
15+ UniversalString , Utf8String ,
1516} ;
1617use core:: convert:: TryFrom ;
1718use data_encoding:: HEXUPPER ;
@@ -71,6 +72,41 @@ newtype_enum! {
7172 }
7273}
7374
75+ /// The DirectoryString type is defined as a choice of PrintableString, TeletexString,
76+ /// BMPString, UTF8String, and UniversalString.
77+ ///
78+ /// <pre>
79+ /// RFC 5280, 4.1.2.4. Issuer
80+ /// DirectoryString ::= CHOICE {
81+ /// teletexString TeletexString (SIZE (1..MAX)),
82+ /// printableString PrintableString (SIZE (1..MAX)),
83+ /// universalString UniversalString (SIZE (1..MAX)),
84+ /// utf8String UTF8String (SIZE (1..MAX)),
85+ /// bmpString BMPString (SIZE (1..MAX))
86+ /// }
87+ /// </pre>
88+ #[ derive( Debug , PartialEq , Eq , Choice ) ]
89+ #[ asn1( parse = "DER" , encode = "" ) ]
90+ pub enum DirectoryString < ' a > {
91+ Teletex ( TeletexString < ' a > ) ,
92+ Printable ( PrintableString < ' a > ) ,
93+ Universal ( UniversalString < ' a > ) ,
94+ Utf8 ( Utf8String < ' a > ) ,
95+ Bmp ( BmpString < ' a > ) ,
96+ }
97+
98+ impl fmt:: Display for DirectoryString < ' _ > {
99+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
100+ match self {
101+ DirectoryString :: Teletex ( s) => f. write_str ( s. as_ref ( ) ) ,
102+ DirectoryString :: Printable ( s) => f. write_str ( s. as_ref ( ) ) ,
103+ DirectoryString :: Universal ( s) => f. write_str ( s. as_ref ( ) ) ,
104+ DirectoryString :: Utf8 ( s) => f. write_str ( s. as_ref ( ) ) ,
105+ DirectoryString :: Bmp ( s) => f. write_str ( s. as_ref ( ) ) ,
106+ }
107+ }
108+ }
109+
74110/// A generic attribute type and value
75111///
76112/// These objects are used as [`RelativeDistinguishedName`] components.
@@ -584,6 +620,15 @@ pub(crate) fn parse_serial(input: Input<'_>) -> IResult<Input<'_>, (&[u8], BigUi
584620 Ok ( ( rem, ( slice, big) ) )
585621}
586622
623+ /// Formats a slice to a colon-separated hex string (for ex `01:02:ff:ff`)
624+ pub fn format_serial ( i : & [ u8 ] ) -> String {
625+ let mut s = i. iter ( ) . fold ( String :: with_capacity ( 3 * i. len ( ) ) , |a, b| {
626+ a + & format ! ( "{b:02x}:" )
627+ } ) ;
628+ s. pop ( ) ;
629+ s
630+ }
631+
587632#[ cfg( test) ]
588633mod tests {
589634 use crate :: certificate:: Validity ;
@@ -615,6 +660,12 @@ mod tests {
615660 assert ! ( r. is_ok( ) ) ;
616661 }
617662
663+ #[ test]
664+ fn test_format_serial ( ) {
665+ let b: & [ u8 ] = & [ 1 , 2 , 3 , 4 , 0xff ] ;
666+ assert_eq ! ( "01:02:03:04:ff" , format_serial( b) ) ;
667+ }
668+
618669 #[ test]
619670 fn test_x509_name ( ) {
620671 let name = X509Name {
0 commit comments