der/asn1/
ia5_string.rs
1use crate::{
4 asn1::Any, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, FixedTag, Length,
5 OrdIsValueOrd, Result, StrSlice, Tag,
6};
7use core::{fmt, str};
8
9#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
20pub struct Ia5String<'a> {
21 inner: StrSlice<'a>,
23}
24
25impl<'a> Ia5String<'a> {
26 pub fn new<T>(input: &'a T) -> Result<Self>
28 where
29 T: AsRef<[u8]> + ?Sized,
30 {
31 let input = input.as_ref();
32
33 if input.iter().any(|&c| c > 0x7F) {
35 return Err(Self::TAG.value_error());
36 }
37
38 StrSlice::from_bytes(input)
39 .map(|inner| Self { inner })
40 .map_err(|_| Self::TAG.value_error())
41 }
42
43 pub fn as_str(&self) -> &'a str {
45 self.inner.as_str()
46 }
47
48 pub fn as_bytes(&self) -> &'a [u8] {
50 self.inner.as_bytes()
51 }
52
53 pub fn len(&self) -> Length {
55 self.inner.len()
56 }
57
58 pub fn is_empty(&self) -> bool {
60 self.inner.is_empty()
61 }
62}
63
64impl AsRef<str> for Ia5String<'_> {
65 fn as_ref(&self) -> &str {
66 self.as_str()
67 }
68}
69
70impl AsRef<[u8]> for Ia5String<'_> {
71 fn as_ref(&self) -> &[u8] {
72 self.as_bytes()
73 }
74}
75
76impl<'a> DecodeValue<'a> for Ia5String<'a> {
77 fn decode_value(decoder: &mut Decoder<'a>, length: Length) -> Result<Self> {
78 Self::new(ByteSlice::decode_value(decoder, length)?.as_bytes())
79 }
80}
81
82impl EncodeValue for Ia5String<'_> {
83 fn value_len(&self) -> Result<Length> {
84 self.inner.value_len()
85 }
86
87 fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
88 self.inner.encode_value(encoder)
89 }
90}
91
92impl<'a> FixedTag for Ia5String<'a> {
93 const TAG: Tag = Tag::Ia5String;
94}
95
96impl OrdIsValueOrd for Ia5String<'_> {}
97
98impl<'a> From<&Ia5String<'a>> for Ia5String<'a> {
99 fn from(value: &Ia5String<'a>) -> Ia5String<'a> {
100 *value
101 }
102}
103
104impl<'a> TryFrom<Any<'a>> for Ia5String<'a> {
105 type Error = Error;
106
107 fn try_from(any: Any<'a>) -> Result<Ia5String<'a>> {
108 any.decode_into()
109 }
110}
111
112impl<'a> From<Ia5String<'a>> for Any<'a> {
113 fn from(printable_string: Ia5String<'a>) -> Any<'a> {
114 Any::from_tag_and_value(Tag::Ia5String, printable_string.inner.into())
115 }
116}
117
118impl<'a> From<Ia5String<'a>> for &'a [u8] {
119 fn from(printable_string: Ia5String<'a>) -> &'a [u8] {
120 printable_string.as_bytes()
121 }
122}
123
124impl<'a> fmt::Display for Ia5String<'a> {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 f.write_str(self.as_str())
127 }
128}
129
130impl<'a> fmt::Debug for Ia5String<'a> {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 write!(f, "Ia5String({:?})", self.as_str())
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::Ia5String;
139 use crate::Decodable;
140 use hex_literal::hex;
141
142 #[test]
143 fn parse_bytes() {
144 let example_bytes = hex!("16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d");
145 let printable_string = Ia5String::from_der(&example_bytes).unwrap();
146 assert_eq!(printable_string.as_str(), "test1@rsa.com");
147 }
148}