der/asn1/
printable_string.rs

1//! ASN.1 `PrintableString` support.
2
3use crate::{
4    asn1::Any, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, FixedTag, Length,
5    OrdIsValueOrd, Result, StrSlice, Tag,
6};
7use core::{fmt, str};
8
9/// ASN.1 `PrintableString` type.
10///
11/// Supports a subset the ASCII character set (desribed below).
12///
13/// For UTF-8, use [`Utf8String`][`crate::asn1::Utf8String`] instead. For the
14/// full ASCII character set, use [`Ia5String`][`crate::asn1::Ia5String`].
15///
16/// # Supported characters
17///
18/// The following ASCII characters/ranges are supported:
19///
20/// - `A..Z`
21/// - `a..z`
22/// - `0..9`
23/// - "` `" (i.e. space)
24/// - `\`
25/// - `(`
26/// - `)`
27/// - `+`
28/// - `,`
29/// - `-`
30/// - `.`
31/// - `/`
32/// - `:`
33/// - `=`
34/// - `?`
35#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
36pub struct PrintableString<'a> {
37    /// Inner value
38    inner: StrSlice<'a>,
39}
40
41impl<'a> PrintableString<'a> {
42    /// Create a new ASN.1 `PrintableString`.
43    pub fn new<T>(input: &'a T) -> Result<Self>
44    where
45        T: AsRef<[u8]> + ?Sized,
46    {
47        let input = input.as_ref();
48
49        // Validate all characters are within PrintedString's allowed set
50        for &c in input.iter() {
51            match c {
52                b'A'..=b'Z'
53                | b'a'..=b'z'
54                | b'0'..=b'9'
55                | b' '
56                | b'\''
57                | b'('
58                | b')'
59                | b'+'
60                | b','
61                | b'-'
62                | b'.'
63                | b'/'
64                | b':'
65                | b'='
66                | b'?' => (),
67                _ => return Err(Self::TAG.value_error()),
68            }
69        }
70
71        StrSlice::from_bytes(input)
72            .map(|inner| Self { inner })
73            .map_err(|_| Self::TAG.value_error())
74    }
75
76    /// Borrow the string as a `str`.
77    pub fn as_str(&self) -> &'a str {
78        self.inner.as_str()
79    }
80
81    /// Borrow the string as bytes.
82    pub fn as_bytes(&self) -> &'a [u8] {
83        self.inner.as_bytes()
84    }
85
86    /// Get the length of the inner byte slice.
87    pub fn len(&self) -> Length {
88        self.inner.len()
89    }
90
91    /// Is the inner string empty?
92    pub fn is_empty(&self) -> bool {
93        self.inner.is_empty()
94    }
95}
96
97impl AsRef<str> for PrintableString<'_> {
98    fn as_ref(&self) -> &str {
99        self.as_str()
100    }
101}
102
103impl AsRef<[u8]> for PrintableString<'_> {
104    fn as_ref(&self) -> &[u8] {
105        self.as_bytes()
106    }
107}
108
109impl<'a> DecodeValue<'a> for PrintableString<'a> {
110    fn decode_value(decoder: &mut Decoder<'a>, length: Length) -> Result<Self> {
111        Self::new(ByteSlice::decode_value(decoder, length)?.as_bytes())
112    }
113}
114
115impl<'a> EncodeValue for PrintableString<'a> {
116    fn value_len(&self) -> Result<Length> {
117        self.inner.value_len()
118    }
119
120    fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
121        self.inner.encode_value(encoder)
122    }
123}
124
125impl FixedTag for PrintableString<'_> {
126    const TAG: Tag = Tag::PrintableString;
127}
128
129impl OrdIsValueOrd for PrintableString<'_> {}
130
131impl<'a> From<&PrintableString<'a>> for PrintableString<'a> {
132    fn from(value: &PrintableString<'a>) -> PrintableString<'a> {
133        *value
134    }
135}
136
137impl<'a> TryFrom<Any<'a>> for PrintableString<'a> {
138    type Error = Error;
139
140    fn try_from(any: Any<'a>) -> Result<PrintableString<'a>> {
141        any.decode_into()
142    }
143}
144
145impl<'a> From<PrintableString<'a>> for Any<'a> {
146    fn from(printable_string: PrintableString<'a>) -> Any<'a> {
147        Any::from_tag_and_value(Tag::PrintableString, printable_string.inner.into())
148    }
149}
150
151impl<'a> From<PrintableString<'a>> for &'a [u8] {
152    fn from(printable_string: PrintableString<'a>) -> &'a [u8] {
153        printable_string.as_bytes()
154    }
155}
156
157impl<'a> fmt::Display for PrintableString<'a> {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        f.write_str(self.as_str())
160    }
161}
162
163impl<'a> fmt::Debug for PrintableString<'a> {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        write!(f, "PrintableString({:?})", self.as_str())
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use super::PrintableString;
172    use crate::Decodable;
173
174    #[test]
175    fn parse_bytes() {
176        let example_bytes = &[
177            0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31,
178        ];
179
180        let printable_string = PrintableString::from_der(example_bytes).unwrap();
181        assert_eq!(printable_string.as_str(), "Test User 1");
182    }
183}