der/asn1/
utf8_string.rs
1use crate::{
4 asn1::AnyRef, ord::OrdIsValueOrd, EncodeValue, Error, FixedTag, Length, Result, StrRef, Tag,
5 Writer,
6};
7use core::{fmt, ops::Deref, str};
8
9#[cfg(feature = "alloc")]
10use {
11 crate::{DecodeValue, Header, Reader},
12 alloc::{borrow::ToOwned, string::String},
13};
14
15#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
30pub struct Utf8StringRef<'a> {
31 inner: StrRef<'a>,
33}
34
35impl<'a> Utf8StringRef<'a> {
36 pub fn new<T>(input: &'a T) -> Result<Self>
38 where
39 T: AsRef<[u8]> + ?Sized,
40 {
41 StrRef::from_bytes(input.as_ref()).map(|inner| Self { inner })
42 }
43}
44
45impl_string_type!(Utf8StringRef<'a>, 'a);
46
47impl<'a> Deref for Utf8StringRef<'a> {
48 type Target = StrRef<'a>;
49
50 fn deref(&self) -> &Self::Target {
51 &self.inner
52 }
53}
54
55impl FixedTag for Utf8StringRef<'_> {
56 const TAG: Tag = Tag::Utf8String;
57}
58
59impl<'a> From<&Utf8StringRef<'a>> for Utf8StringRef<'a> {
60 fn from(value: &Utf8StringRef<'a>) -> Utf8StringRef<'a> {
61 *value
62 }
63}
64
65impl<'a> From<Utf8StringRef<'a>> for AnyRef<'a> {
66 fn from(utf_string: Utf8StringRef<'a>) -> AnyRef<'a> {
67 AnyRef::from_tag_and_value(Tag::Utf8String, utf_string.inner.into())
68 }
69}
70
71impl<'a> fmt::Debug for Utf8StringRef<'a> {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(f, "Utf8String({:?})", self.as_str())
74 }
75}
76
77impl<'a> TryFrom<AnyRef<'a>> for &'a str {
78 type Error = Error;
79
80 fn try_from(any: AnyRef<'a>) -> Result<&'a str> {
81 Utf8StringRef::try_from(any).map(|s| s.as_str())
82 }
83}
84
85impl EncodeValue for str {
86 fn value_len(&self) -> Result<Length> {
87 Utf8StringRef::new(self)?.value_len()
88 }
89
90 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
91 Utf8StringRef::new(self)?.encode_value(writer)
92 }
93}
94
95impl FixedTag for str {
96 const TAG: Tag = Tag::Utf8String;
97}
98
99impl OrdIsValueOrd for str {}
100
101#[cfg(feature = "alloc")]
102impl<'a> From<Utf8StringRef<'a>> for String {
103 fn from(s: Utf8StringRef<'a>) -> String {
104 s.as_str().to_owned()
105 }
106}
107
108#[cfg(feature = "alloc")]
109impl<'a> TryFrom<AnyRef<'a>> for String {
110 type Error = Error;
111
112 fn try_from(any: AnyRef<'a>) -> Result<String> {
113 Utf8StringRef::try_from(any).map(|s| s.as_str().to_owned())
114 }
115}
116
117#[cfg(feature = "alloc")]
118impl<'a> DecodeValue<'a> for String {
119 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
120 Ok(String::from_utf8(reader.read_vec(header.length)?)?)
121 }
122}
123
124#[cfg(feature = "alloc")]
125impl EncodeValue for String {
126 fn value_len(&self) -> Result<Length> {
127 Utf8StringRef::new(self)?.value_len()
128 }
129
130 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
131 Utf8StringRef::new(self)?.encode_value(writer)
132 }
133}
134
135#[cfg(feature = "alloc")]
136impl FixedTag for String {
137 const TAG: Tag = Tag::Utf8String;
138}
139
140#[cfg(feature = "alloc")]
141impl OrdIsValueOrd for String {}
142
143#[cfg(test)]
144mod tests {
145 use super::Utf8StringRef;
146 use crate::Decode;
147
148 #[test]
149 fn parse_ascii_bytes() {
150 let example_bytes = &[
151 0x0c, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31,
152 ];
153
154 let utf8_string = Utf8StringRef::from_der(example_bytes).unwrap();
155 assert_eq!(utf8_string.as_str(), "Test User 1");
156 }
157
158 #[test]
159 fn parse_utf8_bytes() {
160 let example_bytes = &[0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0xc3, 0xb3];
161 let utf8_string = Utf8StringRef::from_der(example_bytes).unwrap();
162 assert_eq!(utf8_string.as_str(), "Helló");
163 }
164}