@@ -33,7 +33,6 @@ 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 ;
3736use std:: fmt;
3837use std:: hash:: Hash ;
3938use std:: net:: IpAddr ;
@@ -299,8 +298,7 @@ See also the RFC 5280 sections on the [issuer](https://tools.ietf.org/html/rfc52
299298and [subject](https://tools.ietf.org/html/rfc5280#section-4.1.2.6) fields.
300299*/
301300pub struct DistinguishedName {
302- entries : HashMap < DnType , DnValue > ,
303- order : Vec < DnType > ,
301+ entries : Vec < ( DnType , DnValue ) > ,
304302}
305303
306304impl DistinguishedName {
@@ -309,20 +307,32 @@ impl DistinguishedName {
309307 Self :: default ( )
310308 }
311309 /// Obtains the attribute value for the given attribute type
312- pub fn get ( & self , ty : & DnType ) -> Option < & DnValue > {
313- self . entries . get ( ty)
310+ pub fn get ( & self , ty : & DnType ) -> Vec < & DnValue > {
311+ self . entries
312+ . iter ( )
313+ . filter_map ( |( dn_type, dn_value) | if ty == dn_type { Some ( dn_value) } else { None } )
314+ . collect ( )
314315 }
315316 /// Removes the attribute with the specified DnType
316317 ///
317318 /// Returns true when an actual removal happened, false
318319 /// when no attribute with the specified DnType was
319320 /// found.
320321 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) ;
322+ let mut remove_indices = vec ! [ ] ;
323+ for ( index, ( dn_type, _dn_val) ) in self . entries . iter ( ) . enumerate ( ) {
324+ if dn_type == & ty {
325+ remove_indices. push ( index) ;
326+ }
324327 }
325- removed
328+
329+ let is_remove_indices = !remove_indices. is_empty ( ) ;
330+
331+ for index in remove_indices {
332+ self . entries . remove ( index) ;
333+ }
334+
335+ is_remove_indices
326336 }
327337 /// Inserts or updates an attribute that consists of type and name
328338 ///
@@ -331,20 +341,41 @@ impl DistinguishedName {
331341 /// let mut dn = DistinguishedName::new();
332342 /// dn.push(DnType::OrganizationName, "Crab widgits SE");
333343 /// 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())));
344+ /// assert_eq!(dn.get(&DnType::OrganizationName).get(0) , Some(&DnValue::Utf8String("Crab widgits SE".to_string())).as_ref( ));
345+ /// assert_eq!(dn.get(&DnType::CommonName).get(0) , Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())).as_ref( ));
336346 /// ```
337347 pub fn push ( & mut self , ty : DnType , s : impl Into < DnValue > ) {
338- if !self . entries . contains_key ( & ty) {
339- self . order . push ( ty. clone ( ) ) ;
348+ self . entries . push ( ( ty, s. into ( ) ) ) ;
349+ }
350+
351+ /// Replaces the *fist occurrence* of a type with a new value.
352+ /// This is a convenience function to avoid duplicating values.
353+ ///
354+ /// 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.
355+ ///
356+ /// ```
357+ /// # use rcgen::{DistinguishedName, DnType, DnValue};
358+ /// let mut dn = DistinguishedName::new();
359+ /// dn.push(DnType::CommonName, DnValue::PrintableString("Master Cert".try_into().unwrap()));
360+ /// assert_eq!(dn.get(&DnType::CommonName).get(0), Some(&DnValue::PrintableString("Master Cert".try_into().unwrap())).as_ref());
361+ /// dn.push(DnType::CommonName, DnValue::PrintableString("Other Master Cert".try_into().unwrap()));
362+ /// assert_eq!(dn.get(&DnType::CommonName).get(1), Some(&DnValue::PrintableString("Other Master Cert".try_into().unwrap())).as_ref());
363+ /// ```
364+ pub fn replace_or_push ( & mut self , ty : DnType , s : impl Into < DnValue > ) {
365+ for ( dn_type, dn_value) in self . entries . iter_mut ( ) {
366+ if * dn_type == ty {
367+ * dn_value = s. into ( ) ;
368+ return ;
369+ }
340370 }
341- self . entries . insert ( ty, s. into ( ) ) ;
371+
372+ self . push ( ty, s)
342373 }
374+
343375 /// Iterate over the entries
344376 pub fn iter ( & self ) -> DistinguishedNameIterator < ' _ > {
345377 DistinguishedNameIterator {
346- distinguished_name : self ,
347- iter : self . order . iter ( ) ,
378+ iter : self . entries . iter ( ) ,
348379 }
349380 }
350381
@@ -397,17 +428,14 @@ impl DistinguishedName {
397428Iterator over [`DistinguishedName`] entries
398429*/
399430pub struct DistinguishedNameIterator < ' a > {
400- distinguished_name : & ' a DistinguishedName ,
401- iter : std:: slice:: Iter < ' a , DnType > ,
431+ iter : std:: slice:: Iter < ' a , ( DnType , DnValue ) > ,
402432}
403433
404434impl < ' a > Iterator for DistinguishedNameIterator < ' a > {
405435 type Item = ( & ' a DnType , & ' a DnValue ) ;
406436
407437 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) ) )
438+ self . iter . next ( ) . map ( |( key, value) | ( key, value) )
411439 }
412440}
413441
@@ -568,7 +596,7 @@ fn write_dt_utc_or_generalized(writer: DERWriter, dt: OffsetDateTime) {
568596 }
569597}
570598
571- fn write_distinguished_name ( writer : DERWriter , dn : & DistinguishedName ) {
599+ fn write_distinguished_name ( writer : DERWriter , dn : DistinguishedName ) {
572600 writer. write_sequence ( |writer| {
573601 for ( ty, content) in dn. iter ( ) {
574602 writer. next ( ) . write_set ( |writer| {
@@ -596,7 +624,7 @@ fn write_distinguished_name(writer: DERWriter, dn: &DistinguishedName) {
596624 . write_tagged_implicit ( TAG_UNIVERSALSTRING , |writer| {
597625 writer. write_bytes ( s. as_bytes ( ) )
598626 } ) ,
599- DnValue :: Utf8String ( s) => writer. next ( ) . write_utf8_string ( s) ,
627+ DnValue :: Utf8String ( s) => writer. next ( ) . write_utf8_string ( s. as_str ( ) ) ,
600628 }
601629 } ) ;
602630 } ) ;
0 commit comments