@@ -33,7 +33,7 @@ println!("{}", key_pair.serialize_pem());
3333#![ cfg_attr( docsrs, feature( doc_cfg, doc_auto_cfg) ) ]
3434#![ warn( unreachable_pub) ]
3535
36- use std:: collections:: HashMap ;
36+ use std:: collections:: VecDeque ;
3737use std:: fmt;
3838use std:: hash:: Hash ;
3939use std:: net:: IpAddr ;
@@ -299,8 +299,7 @@ See also the RFC 5280 sections on the [issuer](https://tools.ietf.org/html/rfc52
299299and [subject](https://tools.ietf.org/html/rfc5280#section-4.1.2.6) fields.
300300*/
301301pub struct DistinguishedName {
302- entries : HashMap < DnType , DnValue > ,
303- order : Vec < DnType > ,
302+ entries : VecDeque < ( DnType , DnValue ) > ,
304303}
305304
306305impl DistinguishedName {
@@ -309,20 +308,32 @@ impl DistinguishedName {
309308 Self :: default ( )
310309 }
311310 /// Obtains the attribute value for the given attribute type
312- pub fn get ( & self , ty : & DnType ) -> Option < & DnValue > {
313- self . entries . get ( ty)
311+ pub fn get ( & self , ty : & DnType ) -> Vec < & DnValue > {
312+ self . entries
313+ . iter ( )
314+ . filter_map ( |( dn_type, dn_value) | if ty == dn_type { Some ( dn_value) } else { None } )
315+ . collect ( )
314316 }
315317 /// Removes the attribute with the specified DnType
316318 ///
317319 /// Returns true when an actual removal happened, false
318320 /// when no attribute with the specified DnType was
319321 /// found.
320322 pub fn remove ( & mut self , ty : DnType ) -> bool {
321- let removed = self . entries . remove ( & ty) . is_some ( ) ;
322- if removed {
323- self . order . retain ( |ty_o| & ty != ty_o) ;
323+ let mut remove_indices = vec ! [ ] ;
324+ for ( index, ( dn_type, _dn_val) ) in self . entries . iter ( ) . enumerate ( ) {
325+ if dn_type == & ty {
326+ remove_indices. push ( index) ;
327+ }
328+ }
329+
330+ let is_remove_indices = !remove_indices. is_empty ( ) ;
331+
332+ for index in remove_indices {
333+ self . entries . remove ( index) ;
324334 }
325- removed
335+
336+ is_remove_indices
326337 }
327338 /// Inserts or updates an attribute that consists of type and name
328339 ///
@@ -331,21 +342,35 @@ impl DistinguishedName {
331342 /// let mut dn = DistinguishedName::new();
332343 /// dn.push(DnType::OrganizationName, "Crab widgits SE");
333344 /// dn.push(DnType::CommonName, DnValue::PrintableString("Master Cert".try_into().unwrap()));
334- /// assert_eq!(dn.get(&DnType::OrganizationName), Some(&DnValue::Utf8String("Crab widgits SE".to_string())));
335- /// assert_eq!(dn.get(&DnType::CommonName), Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())));
345+ /// assert_eq!(dn.get(&DnType::OrganizationName).get(0) , Some(&DnValue::Utf8String("Crab widgits SE".to_string())).as_ref( ));
346+ /// assert_eq!(dn.get(&DnType::CommonName).get(0) , Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())).as_ref( ));
336347 /// ```
337348 pub fn push ( & mut self , ty : DnType , s : impl Into < DnValue > ) {
338- if !self . entries . contains_key ( & ty) {
339- self . order . push ( ty. clone ( ) ) ;
340- }
341- self . entries . insert ( ty, s. into ( ) ) ;
349+ self . entries . push_front ( ( ty, s. into ( ) ) ) ;
342350 }
343- /// Iterate over the entries
344- pub fn iter ( & self ) -> DistinguishedNameIterator < ' _ > {
345- DistinguishedNameIterator {
346- distinguished_name : self ,
347- iter : self . order . iter ( ) ,
351+
352+ /// Replaces the *fist occurrence* of a type with a new value.
353+ /// This is a convenience function to avoid duplicating values.
354+ ///
355+ /// If there are multiple occurrences of a type there is currently no way of changing the besides iterating over the types and values of an existing instance and creating a new instance.
356+ ///
357+ /// ```
358+ /// # use rcgen::{DistinguishedName, DnType, DnValue};
359+ /// let mut dn = DistinguishedName::new();
360+ /// dn.push(DnType::CommonName, DnValue::PrintableString("Master Cert".try_into().unwrap()));
361+ /// assert_eq!(dn.get(&DnType::CommonName).get(0), Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())).as_ref());
362+ /// dn.push(DnType::CommonName, DnValue::PrintableString("Other Master Cert".try_into().unwrap()));
363+ /// assert_eq!(dn.get(&DnType::CommonName).get(0), Some(&DnValue::PrintableString("Other Master Cert".try_into().unwrap())).as_ref());
364+ /// ```
365+ pub fn replace_or_push ( & mut self , ty : DnType , s : impl Into < DnValue > ) {
366+ for ( dn_type, dn_value) in self . entries . iter_mut ( ) {
367+ if * dn_type == ty {
368+ * dn_value = s. into ( ) ;
369+ return ;
370+ }
348371 }
372+
373+ self . push ( ty, s)
349374 }
350375
351376 #[ cfg( feature = "x509-parser" ) ]
@@ -393,21 +418,15 @@ impl DistinguishedName {
393418 }
394419}
395420
396- /**
397- Iterator over [`DistinguishedName`] entries
398- */
399- pub struct DistinguishedNameIterator < ' a > {
400- distinguished_name : & ' a DistinguishedName ,
401- iter : std:: slice:: Iter < ' a , DnType > ,
402- }
403-
404- impl < ' a > Iterator for DistinguishedNameIterator < ' a > {
405- type Item = ( & ' a DnType , & ' a DnValue ) ;
421+ impl Iterator for DistinguishedName {
422+ type Item = ( DnType , DnValue ) ;
406423
407424 fn next ( & mut self ) -> Option < Self :: Item > {
408- self . iter
409- . next ( )
410- . and_then ( |ty| self . distinguished_name . entries . get ( ty) . map ( |v| ( ty, v) ) )
425+ self . entries . pop_back ( )
426+ }
427+
428+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
429+ self . entries . iter ( ) . size_hint ( )
411430 }
412431}
413432
@@ -568,9 +587,9 @@ fn write_dt_utc_or_generalized(writer: DERWriter, dt: OffsetDateTime) {
568587 }
569588}
570589
571- fn write_distinguished_name ( writer : DERWriter , dn : & DistinguishedName ) {
590+ fn write_distinguished_name ( writer : DERWriter , dn : DistinguishedName ) {
572591 writer. write_sequence ( |writer| {
573- for ( ty, content) in dn. iter ( ) {
592+ for ( ty, content) in dn. into_iter ( ) {
574593 writer. next ( ) . write_set ( |writer| {
575594 writer. next ( ) . write_sequence ( |writer| {
576595 writer. next ( ) . write_oid ( & ty. to_oid ( ) ) ;
@@ -596,7 +615,7 @@ fn write_distinguished_name(writer: DERWriter, dn: &DistinguishedName) {
596615 . write_tagged_implicit ( TAG_UNIVERSALSTRING , |writer| {
597616 writer. write_bytes ( s. as_bytes ( ) )
598617 } ) ,
599- DnValue :: Utf8String ( s) => writer. next ( ) . write_utf8_string ( s) ,
618+ DnValue :: Utf8String ( s) => writer. next ( ) . write_utf8_string ( s. as_str ( ) ) ,
600619 }
601620 } ) ;
602621 } ) ;
0 commit comments