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