• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! ASN.1 types supported by the proc macro
2 
3 use proc_macro2::TokenStream;
4 use quote::quote;
5 use std::{fmt, str::FromStr};
6 
7 /// ASN.1 built-in types supported by the `#[asn1(type = "...")]` attribute
8 // TODO(tarcieri): support all ASN.1 types specified in `der::Tag`
9 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
10 pub(crate) enum Asn1Type {
11     /// ASN.1 `BIT STRING`.
12     BitString,
13 
14     /// ASN.1 `IA5String`.
15     Ia5String,
16 
17     /// ASN.1 `GeneralizedTime`.
18     GeneralizedTime,
19 
20     /// ASN.1 `OCTET STRING`.
21     OctetString,
22 
23     /// ASN.1 `PrintableString`.
24     PrintableString,
25 
26     /// ASN.1 `TeletexString`.
27     TeletexString,
28 
29     /// ASN.1 `VideotexString`.
30     VideotexString,
31 
32     /// ASN.1 `UTCTime`.
33     UtcTime,
34 
35     /// ASN.1 `UTF8String`.
36     Utf8String,
37 }
38 
39 impl Asn1Type {
40     /// Get the `::der::Tag` for this ASN.1 type
tag(self) -> TokenStream41     pub fn tag(self) -> TokenStream {
42         match self {
43             Asn1Type::BitString => quote!(::der::Tag::BitString),
44             Asn1Type::Ia5String => quote!(::der::Tag::Ia5String),
45             Asn1Type::GeneralizedTime => quote!(::der::Tag::GeneralizedTime),
46             Asn1Type::OctetString => quote!(::der::Tag::OctetString),
47             Asn1Type::PrintableString => quote!(::der::Tag::PrintableString),
48             Asn1Type::TeletexString => quote!(::der::Tag::TeletexString),
49             Asn1Type::VideotexString => quote!(::der::Tag::VideotexString),
50             Asn1Type::UtcTime => quote!(::der::Tag::UtcTime),
51             Asn1Type::Utf8String => quote!(::der::Tag::Utf8String),
52         }
53     }
54 
55     /// Get a `der::Decoder` object for a particular ASN.1 type
decoder(self) -> TokenStream56     pub fn decoder(self) -> TokenStream {
57         match self {
58             Asn1Type::BitString => quote!(::der::asn1::BitStringRef::decode(reader)?),
59             Asn1Type::Ia5String => quote!(::der::asn1::Ia5StringRef::decode(reader)?),
60             Asn1Type::GeneralizedTime => quote!(::der::asn1::GeneralizedTime::decode(reader)?),
61             Asn1Type::OctetString => quote!(::der::asn1::OctetStringRef::decode(reader)?),
62             Asn1Type::PrintableString => quote!(::der::asn1::PrintableStringRef::decode(reader)?),
63             Asn1Type::TeletexString => quote!(::der::asn1::TeletexStringRef::decode(reader)?),
64             Asn1Type::VideotexString => quote!(::der::asn1::VideotexStringRef::decode(reader)?),
65             Asn1Type::UtcTime => quote!(::der::asn1::UtcTime::decode(reader)?),
66             Asn1Type::Utf8String => quote!(::der::asn1::Utf8StringRef::decode(reader)?),
67         }
68     }
69 
70     /// Get a `der::Encoder` object for a particular ASN.1 type
encoder(self, binding: &TokenStream) -> TokenStream71     pub fn encoder(self, binding: &TokenStream) -> TokenStream {
72         let type_path = self.type_path();
73 
74         match self {
75             Asn1Type::Ia5String
76             | Asn1Type::OctetString
77             | Asn1Type::PrintableString
78             | Asn1Type::TeletexString
79             | Asn1Type::VideotexString
80             | Asn1Type::Utf8String => quote!(#type_path::new(#binding)?),
81             _ => quote!(#type_path::try_from(#binding)?),
82         }
83     }
84 
85     /// Get the Rust type path for a particular ASN.1 type.
86     /// Get a `der::Encoder` object for a particular ASN.1 type
type_path(self) -> TokenStream87     pub fn type_path(self) -> TokenStream {
88         match self {
89             Asn1Type::BitString => quote!(::der::asn1::BitStringRef),
90             Asn1Type::Ia5String => quote!(::der::asn1::Ia5StringRef),
91             Asn1Type::GeneralizedTime => quote!(::der::asn1::GeneralizedTime),
92             Asn1Type::OctetString => quote!(::der::asn1::OctetStringRef),
93             Asn1Type::PrintableString => quote!(::der::asn1::PrintableStringRef),
94             Asn1Type::TeletexString => quote!(::der::asn1::TeletexStringRef),
95             Asn1Type::VideotexString => quote!(::der::asn1::VideotexStringRef),
96             Asn1Type::UtcTime => quote!(::der::asn1::UtcTime),
97             Asn1Type::Utf8String => quote!(::der::asn1::Utf8StringRef),
98         }
99     }
100 }
101 
102 impl FromStr for Asn1Type {
103     type Err = ParseError;
104 
from_str(s: &str) -> Result<Self, ParseError>105     fn from_str(s: &str) -> Result<Self, ParseError> {
106         match s {
107             "BIT STRING" => Ok(Self::BitString),
108             "IA5String" => Ok(Self::Ia5String),
109             "GeneralizedTime" => Ok(Self::GeneralizedTime),
110             "OCTET STRING" => Ok(Self::OctetString),
111             "PrintableString" => Ok(Self::PrintableString),
112             "TeletexString" => Ok(Self::TeletexString),
113             "VideotexString" => Ok(Self::VideotexString),
114             "UTCTime" => Ok(Self::UtcTime),
115             "UTF8String" => Ok(Self::Utf8String),
116             _ => Err(ParseError),
117         }
118     }
119 }
120 
121 impl fmt::Display for Asn1Type {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result122     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123         f.write_str(match self {
124             Asn1Type::BitString => "BIT STRING",
125             Asn1Type::Ia5String => "IA5String",
126             Asn1Type::GeneralizedTime => "GeneralizedTime",
127             Asn1Type::OctetString => "OCTET STRING",
128             Asn1Type::PrintableString => "PrintableString",
129             Asn1Type::TeletexString => "TeletexString",
130             Asn1Type::VideotexString => "VideotexString",
131             Asn1Type::UtcTime => "UTCTime",
132             Asn1Type::Utf8String => "UTF8String",
133         })
134     }
135 }
136 
137 /// Error type
138 #[derive(Debug)]
139 pub(crate) struct ParseError;
140