1 //! ASN.1 `VideotexString` support. 2 3 use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; 4 use core::{fmt, ops::Deref}; 5 6 /// ASN.1 `VideotexString` type. 7 /// 8 /// Supports a subset the ASCII character set (described below). 9 /// 10 /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. 11 /// For the full ASCII character set, use 12 /// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. 13 /// 14 /// This is a zero-copy reference type which borrows from the input data. 15 /// 16 /// # Supported characters 17 /// 18 /// For the practical purposes VideotexString is treated as IA5string, disallowing non-ASCII chars. 19 /// 20 #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] 21 pub struct VideotexStringRef<'a> { 22 /// Inner value 23 inner: StrRef<'a>, 24 } 25 26 impl<'a> VideotexStringRef<'a> { 27 /// Create a new ASN.1 `VideotexString`. new<T>(input: &'a T) -> Result<Self> where T: AsRef<[u8]> + ?Sized,28 pub fn new<T>(input: &'a T) -> Result<Self> 29 where 30 T: AsRef<[u8]> + ?Sized, 31 { 32 let input = input.as_ref(); 33 34 // Validate all characters are within VideotexString's allowed set 35 // FIXME: treat as if it were IA5String 36 if input.iter().any(|&c| c > 0x7F) { 37 return Err(Self::TAG.value_error()); 38 } 39 40 StrRef::from_bytes(input) 41 .map(|inner| Self { inner }) 42 .map_err(|_| Self::TAG.value_error()) 43 } 44 } 45 46 impl_string_type!(VideotexStringRef<'a>, 'a); 47 48 impl<'a> Deref for VideotexStringRef<'a> { 49 type Target = StrRef<'a>; 50 deref(&self) -> &Self::Target51 fn deref(&self) -> &Self::Target { 52 &self.inner 53 } 54 } 55 56 impl FixedTag for VideotexStringRef<'_> { 57 const TAG: Tag = Tag::VideotexString; 58 } 59 60 impl<'a> From<&VideotexStringRef<'a>> for VideotexStringRef<'a> { from(value: &VideotexStringRef<'a>) -> VideotexStringRef<'a>61 fn from(value: &VideotexStringRef<'a>) -> VideotexStringRef<'a> { 62 *value 63 } 64 } 65 66 impl<'a> From<VideotexStringRef<'a>> for AnyRef<'a> { from(printable_string: VideotexStringRef<'a>) -> AnyRef<'a>67 fn from(printable_string: VideotexStringRef<'a>) -> AnyRef<'a> { 68 AnyRef::from_tag_and_value(Tag::VideotexString, printable_string.inner.into()) 69 } 70 } 71 72 impl<'a> From<VideotexStringRef<'a>> for &'a [u8] { from(printable_string: VideotexStringRef<'a>) -> &'a [u8]73 fn from(printable_string: VideotexStringRef<'a>) -> &'a [u8] { 74 printable_string.as_bytes() 75 } 76 } 77 78 impl<'a> fmt::Debug for VideotexStringRef<'a> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 80 write!(f, "VideotexString({:?})", self.as_str()) 81 } 82 } 83 84 #[cfg(test)] 85 mod tests { 86 use super::VideotexStringRef; 87 use crate::Decode; 88 89 #[test] parse_bytes()90 fn parse_bytes() { 91 let example_bytes = &[ 92 0x15, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31, 93 ]; 94 95 let printable_string = VideotexStringRef::from_der(example_bytes).unwrap(); 96 assert_eq!(printable_string.as_str(), "Test User 1"); 97 } 98 } 99