1 //! ASN.1 `PrintableString` support. 2 3 use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; 4 use core::{fmt, ops::Deref}; 5 6 macro_rules! impl_printable_string { 7 ($type: ty) => { 8 impl_printable_string!($type,); 9 }; 10 ($type: ty, $($li: lifetime)?) => { 11 impl_string_type!($type, $($li),*); 12 13 impl<$($li),*> FixedTag for $type { 14 const TAG: Tag = Tag::PrintableString; 15 } 16 17 impl<$($li),*> fmt::Debug for $type { 18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19 write!(f, "PrintableString({:?})", self.as_str()) 20 } 21 } 22 }; 23 } 24 25 /// ASN.1 `PrintableString` type. 26 /// 27 /// Supports a subset the ASCII character set (described below). 28 /// 29 /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. 30 /// For the full ASCII character set, use 31 /// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. 32 /// 33 /// This is a zero-copy reference type which borrows from the input data. 34 /// 35 /// # Supported characters 36 /// 37 /// The following ASCII characters/ranges are supported: 38 /// 39 /// - `A..Z` 40 /// - `a..z` 41 /// - `0..9` 42 /// - "` `" (i.e. space) 43 /// - `\` 44 /// - `(` 45 /// - `)` 46 /// - `+` 47 /// - `,` 48 /// - `-` 49 /// - `.` 50 /// - `/` 51 /// - `:` 52 /// - `=` 53 /// - `?` 54 #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] 55 pub struct PrintableStringRef<'a> { 56 /// Inner value 57 inner: StrRef<'a>, 58 } 59 60 impl<'a> PrintableStringRef<'a> { 61 /// Create a new ASN.1 `PrintableString`. new<T>(input: &'a T) -> Result<Self> where T: AsRef<[u8]> + ?Sized,62 pub fn new<T>(input: &'a T) -> Result<Self> 63 where 64 T: AsRef<[u8]> + ?Sized, 65 { 66 let input = input.as_ref(); 67 68 // Validate all characters are within PrintableString's allowed set 69 for &c in input.iter() { 70 match c { 71 b'A'..=b'Z' 72 | b'a'..=b'z' 73 | b'0'..=b'9' 74 | b' ' 75 | b'\'' 76 | b'(' 77 | b')' 78 | b'+' 79 | b',' 80 | b'-' 81 | b'.' 82 | b'/' 83 | b':' 84 | b'=' 85 | b'?' => (), 86 _ => return Err(Self::TAG.value_error()), 87 } 88 } 89 90 StrRef::from_bytes(input) 91 .map(|inner| Self { inner }) 92 .map_err(|_| Self::TAG.value_error()) 93 } 94 } 95 96 impl_printable_string!(PrintableStringRef<'a>, 'a); 97 98 impl<'a> Deref for PrintableStringRef<'a> { 99 type Target = StrRef<'a>; 100 deref(&self) -> &Self::Target101 fn deref(&self) -> &Self::Target { 102 &self.inner 103 } 104 } 105 impl<'a> From<&PrintableStringRef<'a>> for PrintableStringRef<'a> { from(value: &PrintableStringRef<'a>) -> PrintableStringRef<'a>106 fn from(value: &PrintableStringRef<'a>) -> PrintableStringRef<'a> { 107 *value 108 } 109 } 110 111 impl<'a> From<PrintableStringRef<'a>> for AnyRef<'a> { from(printable_string: PrintableStringRef<'a>) -> AnyRef<'a>112 fn from(printable_string: PrintableStringRef<'a>) -> AnyRef<'a> { 113 AnyRef::from_tag_and_value(Tag::PrintableString, printable_string.inner.into()) 114 } 115 } 116 117 #[cfg(feature = "alloc")] 118 pub use self::allocation::PrintableString; 119 120 #[cfg(feature = "alloc")] 121 mod allocation { 122 use super::PrintableStringRef; 123 124 use crate::{ 125 asn1::AnyRef, 126 referenced::{OwnedToRef, RefToOwned}, 127 BytesRef, Error, FixedTag, Result, StrOwned, Tag, 128 }; 129 use alloc::string::String; 130 use core::{fmt, ops::Deref}; 131 132 /// ASN.1 `PrintableString` type. 133 /// 134 /// Supports a subset the ASCII character set (described below). 135 /// 136 /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. 137 /// For the full ASCII character set, use 138 /// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. 139 /// 140 /// # Supported characters 141 /// 142 /// The following ASCII characters/ranges are supported: 143 /// 144 /// - `A..Z` 145 /// - `a..z` 146 /// - `0..9` 147 /// - "` `" (i.e. space) 148 /// - `\` 149 /// - `(` 150 /// - `)` 151 /// - `+` 152 /// - `,` 153 /// - `-` 154 /// - `.` 155 /// - `/` 156 /// - `:` 157 /// - `=` 158 /// - `?` 159 #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] 160 pub struct PrintableString { 161 /// Inner value 162 inner: StrOwned, 163 } 164 165 impl PrintableString { 166 /// Create a new ASN.1 `PrintableString`. new<T>(input: &T) -> Result<Self> where T: AsRef<[u8]> + ?Sized,167 pub fn new<T>(input: &T) -> Result<Self> 168 where 169 T: AsRef<[u8]> + ?Sized, 170 { 171 let input = input.as_ref(); 172 PrintableStringRef::new(input)?; 173 174 StrOwned::from_bytes(input) 175 .map(|inner| Self { inner }) 176 .map_err(|_| Self::TAG.value_error()) 177 } 178 } 179 180 impl_printable_string!(PrintableString); 181 182 impl Deref for PrintableString { 183 type Target = StrOwned; 184 deref(&self) -> &Self::Target185 fn deref(&self) -> &Self::Target { 186 &self.inner 187 } 188 } 189 190 impl<'a> From<PrintableStringRef<'a>> for PrintableString { from(value: PrintableStringRef<'a>) -> PrintableString191 fn from(value: PrintableStringRef<'a>) -> PrintableString { 192 let inner = 193 StrOwned::from_bytes(value.inner.as_bytes()).expect("Invalid PrintableString"); 194 Self { inner } 195 } 196 } 197 198 impl<'a> From<&'a PrintableString> for AnyRef<'a> { from(printable_string: &'a PrintableString) -> AnyRef<'a>199 fn from(printable_string: &'a PrintableString) -> AnyRef<'a> { 200 AnyRef::from_tag_and_value( 201 Tag::PrintableString, 202 BytesRef::new(printable_string.inner.as_bytes()).expect("Invalid PrintableString"), 203 ) 204 } 205 } 206 207 impl<'a> RefToOwned<'a> for PrintableStringRef<'a> { 208 type Owned = PrintableString; ref_to_owned(&self) -> Self::Owned209 fn ref_to_owned(&self) -> Self::Owned { 210 PrintableString { 211 inner: self.inner.ref_to_owned(), 212 } 213 } 214 } 215 216 impl OwnedToRef for PrintableString { 217 type Borrowed<'a> = PrintableStringRef<'a>; owned_to_ref(&self) -> Self::Borrowed<'_>218 fn owned_to_ref(&self) -> Self::Borrowed<'_> { 219 PrintableStringRef { 220 inner: self.inner.owned_to_ref(), 221 } 222 } 223 } 224 225 impl TryFrom<String> for PrintableString { 226 type Error = Error; 227 try_from(input: String) -> Result<Self>228 fn try_from(input: String) -> Result<Self> { 229 PrintableStringRef::new(&input)?; 230 231 StrOwned::new(input) 232 .map(|inner| Self { inner }) 233 .map_err(|_| Self::TAG.value_error()) 234 } 235 } 236 } 237 238 #[cfg(test)] 239 mod tests { 240 use super::PrintableStringRef; 241 use crate::Decode; 242 243 #[test] parse_bytes()244 fn parse_bytes() { 245 let example_bytes = &[ 246 0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31, 247 ]; 248 249 let printable_string = PrintableStringRef::from_der(example_bytes).unwrap(); 250 assert_eq!(printable_string.as_str(), "Test User 1"); 251 } 252 } 253