polyproto/types/der/asn1/
ia5string.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use std::hash::Hash;
6use std::ops::{Deref, DerefMut};
7
8#[derive(Debug, PartialEq, Clone, Eq, PartialOrd, Ord)]
9/// Wrapper around [der::asn1::Ia5String], which provides serde support, if the `serde` feature is
10/// enabled.
11///
12/// ASN.1 `IA5String` type.
13///
14/// Supports the [International Alphabet No. 5 (IA5)] character encoding, i.e.
15/// the lower 128 characters of the ASCII alphabet. (Note: IA5 is now
16/// technically known as the International Reference Alphabet or IRA as
17/// specified in the ITU-T's T.50 recommendation).
18///
19/// For UTF-8, use [`String`][`alloc::string::String`].
20///
21/// [International Alphabet No. 5 (IA5)]: https://en.wikipedia.org/wiki/T.50_%28standard%29
22pub struct Ia5String(der::asn1::Ia5String);
23
24impl Ia5String {
25    /// Create a new `IA5String`.
26    pub fn new<T>(input: &T) -> Result<Self, der::Error>
27    where
28        T: AsRef<[u8]> + ?Sized,
29    {
30        Ok(Ia5String(der::asn1::Ia5String::new(input)?))
31    }
32}
33
34impl Deref for Ia5String {
35    type Target = der::asn1::Ia5String;
36
37    fn deref(&self) -> &Self::Target {
38        &self.0
39    }
40}
41
42impl DerefMut for Ia5String {
43    fn deref_mut(&mut self) -> &mut Self::Target {
44        &mut self.0
45    }
46}
47
48impl From<der::asn1::Ia5String> for Ia5String {
49    fn from(s: der::asn1::Ia5String) -> Self {
50        Self(s)
51    }
52}
53
54impl From<Ia5String> for der::asn1::Ia5String {
55    fn from(s: Ia5String) -> Self {
56        s.0
57    }
58}
59
60impl Hash for Ia5String {
61    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
62        self.as_bytes().hash(state);
63    }
64}
65
66#[cfg(feature = "serde")]
67mod serde_support {
68    use super::Ia5String;
69    use serde::de::Visitor;
70    use serde::{Deserialize, Serialize};
71
72    impl<'de> Deserialize<'de> for Ia5String {
73        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
74        where
75            D: serde::Deserializer<'de>,
76        {
77            deserializer.deserialize_str(Ia5StringVisitor)
78        }
79    }
80
81    struct Ia5StringVisitor;
82
83    impl Visitor<'_> for Ia5StringVisitor {
84        type Value = Ia5String;
85
86        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
87            formatter.write_str(
88                "a concatenation of characters from the IA5 character set in &str format",
89            )
90        }
91
92        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
93        where
94            E: serde::de::Error,
95        {
96            Ok(Ia5String(match der::asn1::Ia5String::new(&v.to_string()) {
97                Ok(val) => val,
98                Err(e) => return Err(E::custom(e)),
99            }))
100        }
101    }
102
103    impl Serialize for Ia5String {
104        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
105        where
106            S: serde::Serializer,
107        {
108            serializer.serialize_str(self.0.to_string().as_str())
109        }
110    }
111}
112
113#[cfg(test)]
114mod test {
115    use super::*;
116    use serde_test::{Token, assert_de_tokens, assert_tokens};
117
118    #[test]
119    #[cfg(feature = "serde")]
120    fn ia5string_ser() {
121        let ia5string = Ia5String(der::asn1::Ia5String::new("test").unwrap());
122        assert_tokens(&ia5string, &[Token::Str("test")]);
123        let ia5string = Ia5String(der::asn1::Ia5String::new(&64u64.to_string()).unwrap());
124        assert_tokens(&ia5string, &[Token::Str("64")]);
125    }
126
127    #[test]
128    #[cfg(feature = "serde")]
129    fn ia5string_de() {
130        let ia5string = Ia5String(der::asn1::Ia5String::new("test").unwrap());
131        assert_de_tokens(&ia5string, &[Token::Str("test")]);
132        let ia5string = Ia5String(der::asn1::Ia5String::new(64u64.to_string().as_str()).unwrap());
133        assert_de_tokens(&ia5string, &[Token::Str("64")]);
134    }
135}