1 //! ASN.1 `TeletexString` support. 2 //! 3 use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; 4 use core::{fmt, ops::Deref}; 5 6 macro_rules! impl_teletex_string { 7 ($type: ty) => { 8 impl_teletex_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::TeletexString; 15 } 16 17 impl<$($li),*> fmt::Debug for $type { 18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 19 write!(f, "TeletexString({:?})", self.as_str()) 20 } 21 } 22 }; 23 } 24 25 /// ASN.1 `TeletexString` 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 standard defines a complex character set allowed in this type. However, quoting the ASN.1 38 /// mailing list, "a sizable volume of software in the world treats TeletexString (T61String) as a 39 /// simple 8-bit string with mostly Windows Latin 1 (superset of iso-8859-1) encoding". 40 /// 41 #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] 42 pub struct TeletexStringRef<'a> { 43 /// Inner value 44 inner: StrRef<'a>, 45 } 46 47 impl<'a> TeletexStringRef<'a> { 48 /// Create a new ASN.1 `TeletexString`. new<T>(input: &'a T) -> Result<Self> where T: AsRef<[u8]> + ?Sized,49 pub fn new<T>(input: &'a T) -> Result<Self> 50 where 51 T: AsRef<[u8]> + ?Sized, 52 { 53 let input = input.as_ref(); 54 55 // FIXME: support higher part of the charset 56 if input.iter().any(|&c| c > 0x7F) { 57 return Err(Self::TAG.value_error()); 58 } 59 60 StrRef::from_bytes(input) 61 .map(|inner| Self { inner }) 62 .map_err(|_| Self::TAG.value_error()) 63 } 64 } 65 66 impl_teletex_string!(TeletexStringRef<'a>, 'a); 67 68 impl<'a> Deref for TeletexStringRef<'a> { 69 type Target = StrRef<'a>; 70 deref(&self) -> &Self::Target71 fn deref(&self) -> &Self::Target { 72 &self.inner 73 } 74 } 75 76 impl<'a> From<&TeletexStringRef<'a>> for TeletexStringRef<'a> { from(value: &TeletexStringRef<'a>) -> TeletexStringRef<'a>77 fn from(value: &TeletexStringRef<'a>) -> TeletexStringRef<'a> { 78 *value 79 } 80 } 81 82 impl<'a> From<TeletexStringRef<'a>> for AnyRef<'a> { from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a>83 fn from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a> { 84 AnyRef::from_tag_and_value(Tag::TeletexString, teletex_string.inner.into()) 85 } 86 } 87 88 #[cfg(feature = "alloc")] 89 pub use self::allocation::TeletexString; 90 91 #[cfg(feature = "alloc")] 92 mod allocation { 93 use super::TeletexStringRef; 94 95 use crate::{ 96 asn1::AnyRef, 97 referenced::{OwnedToRef, RefToOwned}, 98 BytesRef, Error, FixedTag, Result, StrOwned, Tag, 99 }; 100 use alloc::string::String; 101 use core::{fmt, ops::Deref}; 102 103 /// ASN.1 `TeletexString` type. 104 /// 105 /// Supports a subset the ASCII character set (described below). 106 /// 107 /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. 108 /// For the full ASCII character set, use 109 /// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. 110 /// 111 /// # Supported characters 112 /// 113 /// The standard defines a complex character set allowed in this type. However, quoting the ASN.1 114 /// mailing list, "a sizable volume of software in the world treats TeletexString (T61String) as a 115 /// simple 8-bit string with mostly Windows Latin 1 (superset of iso-8859-1) encoding". 116 /// 117 #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] 118 pub struct TeletexString { 119 /// Inner value 120 inner: StrOwned, 121 } 122 123 impl TeletexString { 124 /// Create a new ASN.1 `TeletexString`. new<T>(input: &T) -> Result<Self> where T: AsRef<[u8]> + ?Sized,125 pub fn new<T>(input: &T) -> Result<Self> 126 where 127 T: AsRef<[u8]> + ?Sized, 128 { 129 let input = input.as_ref(); 130 131 TeletexStringRef::new(input)?; 132 133 StrOwned::from_bytes(input) 134 .map(|inner| Self { inner }) 135 .map_err(|_| Self::TAG.value_error()) 136 } 137 } 138 139 impl_teletex_string!(TeletexString); 140 141 impl Deref for TeletexString { 142 type Target = StrOwned; 143 deref(&self) -> &Self::Target144 fn deref(&self) -> &Self::Target { 145 &self.inner 146 } 147 } 148 149 impl<'a> From<TeletexStringRef<'a>> for TeletexString { from(value: TeletexStringRef<'a>) -> TeletexString150 fn from(value: TeletexStringRef<'a>) -> TeletexString { 151 let inner = 152 StrOwned::from_bytes(value.inner.as_bytes()).expect("Invalid TeletexString"); 153 Self { inner } 154 } 155 } 156 157 impl<'a> From<&'a TeletexString> for AnyRef<'a> { from(teletex_string: &'a TeletexString) -> AnyRef<'a>158 fn from(teletex_string: &'a TeletexString) -> AnyRef<'a> { 159 AnyRef::from_tag_and_value( 160 Tag::TeletexString, 161 BytesRef::new(teletex_string.inner.as_bytes()).expect("Invalid TeletexString"), 162 ) 163 } 164 } 165 166 impl<'a> RefToOwned<'a> for TeletexStringRef<'a> { 167 type Owned = TeletexString; ref_to_owned(&self) -> Self::Owned168 fn ref_to_owned(&self) -> Self::Owned { 169 TeletexString { 170 inner: self.inner.ref_to_owned(), 171 } 172 } 173 } 174 175 impl OwnedToRef for TeletexString { 176 type Borrowed<'a> = TeletexStringRef<'a>; owned_to_ref(&self) -> Self::Borrowed<'_>177 fn owned_to_ref(&self) -> Self::Borrowed<'_> { 178 TeletexStringRef { 179 inner: self.inner.owned_to_ref(), 180 } 181 } 182 } 183 184 impl TryFrom<String> for TeletexString { 185 type Error = Error; 186 try_from(input: String) -> Result<Self>187 fn try_from(input: String) -> Result<Self> { 188 TeletexStringRef::new(&input)?; 189 190 StrOwned::new(input) 191 .map(|inner| Self { inner }) 192 .map_err(|_| Self::TAG.value_error()) 193 } 194 } 195 } 196 197 #[cfg(test)] 198 mod tests { 199 use super::TeletexStringRef; 200 use crate::Decode; 201 use crate::SliceWriter; 202 203 #[test] parse_bytes()204 fn parse_bytes() { 205 let example_bytes = &[ 206 0x14, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31, 207 ]; 208 209 let teletex_string = TeletexStringRef::from_der(example_bytes).unwrap(); 210 assert_eq!(teletex_string.as_str(), "Test User 1"); 211 let mut out = [0_u8; 30]; 212 let mut writer = SliceWriter::new(&mut out); 213 writer.encode(&teletex_string).unwrap(); 214 let encoded = writer.finish().unwrap(); 215 assert_eq!(encoded, example_bytes); 216 } 217 } 218