Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

x509_cert/ext/pkix/name/
dirstr.rs

1use alloc::borrow::Cow;
2use alloc::string::String;
3use alloc::string::ToString;
4use der::{
5    Choice, ValueOrd,
6    asn1::{Any, BmpString, PrintableString, TeletexString},
7};
8
9/// DirectoryString as defined in [RFC 5280 Section 4.2.1.4].
10///
11/// ASN.1 structure for DirectoryString is below.
12///
13/// ```text
14/// DirectoryString ::= CHOICE {
15///     teletexString           TeletexString (SIZE (1..MAX)),
16///     printableString         PrintableString (SIZE (1..MAX)),
17///     universalString         UniversalString (SIZE (1..MAX)),
18///     utf8String              UTF8String (SIZE (1..MAX)),
19///     bmpString               BMPString (SIZE (1..MAX))
20/// }
21/// ```
22///
23/// Further, [RFC 5280 Section 4.2.1.4] states:
24///
25/// ```text
26/// The DirectoryString type is defined as a choice of PrintableString,
27/// TeletexString, BMPString, UTF8String, and UniversalString.  CAs
28/// conforming to this profile MUST use either the PrintableString or
29/// UTF8String encoding of DirectoryString, with two exceptions.  When
30/// CAs have previously issued certificates with issuer fields with
31/// attributes encoded using TeletexString, BMPString, or
32/// UniversalString, then the CA MAY continue to use these encodings of
33/// the DirectoryString to preserve backward compatibility.  Also, new
34/// CAs that are added to a domain where existing CAs issue certificates
35/// with issuer fields with attributes encoded using TeletexString,
36/// BMPString, or UniversalString MAY encode attributes that they share
37/// with the existing CAs using the same encodings as the existing CAs
38/// use.
39/// ```
40///
41/// The implication of the above paragraph is that `PrintableString` and
42/// `UTF8String` are the new types and the other types are legacy. Until
43/// the need arises, we only support `PrintableString` and `UTF8String`.
44///
45/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
46#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)]
47#[allow(missing_docs)]
48pub enum DirectoryString {
49    #[asn1(type = "PrintableString")]
50    PrintableString(PrintableString),
51
52    #[asn1(type = "TeletexString")]
53    TeletexString(TeletexString),
54
55    #[asn1(type = "UTF8String")]
56    Utf8String(String),
57
58    #[asn1(type = "BMPString")]
59    BmpString(BmpString),
60}
61
62impl<'a> TryFrom<&'a Any> for DirectoryString {
63    type Error = der::Error;
64    fn try_from(any: &'a Any) -> der::Result<Self> {
65        any.decode_as()
66    }
67}
68
69impl DirectoryString {
70    /// Returns `Borrowed` variant for UTF-8 compatible strings
71    /// and `Owned` variant otherwise.
72    pub fn value(&self) -> Cow<'_, str> {
73        match self {
74            Self::PrintableString(s) => Cow::Borrowed(s.as_ref()),
75            Self::TeletexString(s) => Cow::Borrowed(s.as_ref()),
76            Self::Utf8String(s) => Cow::Borrowed(s.as_ref()),
77            Self::BmpString(s) => Cow::Owned(s.to_string()),
78        }
79    }
80
81    /// Returns `&str` for `PrintableString`, `TeletexString` and `Utf8String`
82    ///
83    /// Warning: Returns `""` empty string for [`DirectoryString::BmpString`] variant
84    #[deprecated(since = "0.3.0-pre.0", note = "use `DirectoryString::value` instead")]
85    #[allow(clippy::should_implement_trait)]
86    pub fn as_ref(&self) -> &str {
87        match self {
88            Self::PrintableString(s) => s.as_ref(),
89            Self::TeletexString(s) => s.as_ref(),
90            Self::Utf8String(s) => s.as_ref(),
91            // BMPString is not str-compatible
92            Self::BmpString(_s) => "",
93        }
94    }
95}
96
97impl From<DirectoryString> for String {
98    fn from(value: DirectoryString) -> Self {
99        value.value().into_owned()
100    }
101}