@@ -33,7 +33,6 @@ println!("{}", key_pair.serialize_pem());
33
33
#![ cfg_attr( docsrs, feature( doc_cfg, doc_auto_cfg) ) ]
34
34
#![ warn( unreachable_pub) ]
35
35
36
- use std:: collections:: HashMap ;
37
36
use std:: fmt;
38
37
use std:: hash:: Hash ;
39
38
use std:: net:: IpAddr ;
@@ -299,8 +298,7 @@ See also the RFC 5280 sections on the [issuer](https://tools.ietf.org/html/rfc52
299
298
and [subject](https://tools.ietf.org/html/rfc5280#section-4.1.2.6) fields.
300
299
*/
301
300
pub struct DistinguishedName {
302
- entries : HashMap < DnType , DnValue > ,
303
- order : Vec < DnType > ,
301
+ entries : Vec < ( DnType , DnValue ) > ,
304
302
}
305
303
306
304
impl DistinguishedName {
@@ -309,20 +307,32 @@ impl DistinguishedName {
309
307
Self :: default ( )
310
308
}
311
309
/// 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 ( )
314
315
}
315
316
/// Removes the attribute with the specified DnType
316
317
///
317
318
/// Returns true when an actual removal happened, false
318
319
/// when no attribute with the specified DnType was
319
320
/// found.
320
321
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
+ }
324
327
}
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
326
336
}
327
337
/// Inserts or updates an attribute that consists of type and name
328
338
///
@@ -331,20 +341,41 @@ impl DistinguishedName {
331
341
/// let mut dn = DistinguishedName::new();
332
342
/// dn.push(DnType::OrganizationName, "Crab widgits SE");
333
343
/// 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( ));
336
346
/// ```
337
347
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
+ }
340
370
}
341
- self . entries . insert ( ty, s. into ( ) ) ;
371
+
372
+ self . push ( ty, s)
342
373
}
374
+
343
375
/// Iterate over the entries
344
376
pub fn iter ( & self ) -> DistinguishedNameIterator < ' _ > {
345
377
DistinguishedNameIterator {
346
- distinguished_name : self ,
347
- iter : self . order . iter ( ) ,
378
+ iter : self . entries . iter ( ) ,
348
379
}
349
380
}
350
381
@@ -397,17 +428,14 @@ impl DistinguishedName {
397
428
Iterator over [`DistinguishedName`] entries
398
429
*/
399
430
pub struct DistinguishedNameIterator < ' a > {
400
- distinguished_name : & ' a DistinguishedName ,
401
- iter : std:: slice:: Iter < ' a , DnType > ,
431
+ iter : std:: slice:: Iter < ' a , ( DnType , DnValue ) > ,
402
432
}
403
433
404
434
impl < ' a > Iterator for DistinguishedNameIterator < ' a > {
405
435
type Item = ( & ' a DnType , & ' a DnValue ) ;
406
436
407
437
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) )
411
439
}
412
440
}
413
441
@@ -568,7 +596,7 @@ fn write_dt_utc_or_generalized(writer: DERWriter, dt: OffsetDateTime) {
568
596
}
569
597
}
570
598
571
- fn write_distinguished_name ( writer : DERWriter , dn : & DistinguishedName ) {
599
+ fn write_distinguished_name ( writer : DERWriter , dn : DistinguishedName ) {
572
600
writer. write_sequence ( |writer| {
573
601
for ( ty, content) in dn. iter ( ) {
574
602
writer. next ( ) . write_set ( |writer| {
@@ -596,7 +624,7 @@ fn write_distinguished_name(writer: DERWriter, dn: &DistinguishedName) {
596
624
. write_tagged_implicit ( TAG_UNIVERSALSTRING , |writer| {
597
625
writer. write_bytes ( s. as_bytes ( ) )
598
626
} ) ,
599
- DnValue :: Utf8String ( s) => writer. next ( ) . write_utf8_string ( s) ,
627
+ DnValue :: Utf8String ( s) => writer. next ( ) . write_utf8_string ( s. as_str ( ) ) ,
600
628
}
601
629
} ) ;
602
630
} ) ;
0 commit comments