use proc_macro2::TokenStream;
use quote::quote;
use std::{fmt, str::FromStr};
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub(crate) enum Asn1Type {
BitString,
Ia5String,
GeneralizedTime,
OctetString,
PrintableString,
TeletexString,
VideotexString,
UtcTime,
Utf8String,
BmpString,
}
impl Asn1Type {
pub fn tag(self) -> TokenStream {
match self {
Asn1Type::BitString => quote!(::der::Tag::BitString),
Asn1Type::Ia5String => quote!(::der::Tag::Ia5String),
Asn1Type::GeneralizedTime => quote!(::der::Tag::GeneralizedTime),
Asn1Type::OctetString => quote!(::der::Tag::OctetString),
Asn1Type::PrintableString => quote!(::der::Tag::PrintableString),
Asn1Type::TeletexString => quote!(::der::Tag::TeletexString),
Asn1Type::VideotexString => quote!(::der::Tag::VideotexString),
Asn1Type::UtcTime => quote!(::der::Tag::UtcTime),
Asn1Type::Utf8String => quote!(::der::Tag::Utf8String),
Asn1Type::BmpString => quote!(::der::Tag::BmpString),
}
}
pub fn decoder(self) -> TokenStream {
let type_path = self.type_path();
quote!(<#type_path>::decode(reader)?)
}
pub fn decoder_optional(self) -> TokenStream {
let type_path = self.type_path();
quote!(Option::<#type_path>::decode(reader)?)
}
pub fn value_decoder(self) -> TokenStream {
let type_path = self.type_path();
quote!(<#type_path>::decode_value(reader, header)?)
}
pub fn value_decoder_optional(self) -> TokenStream {
let type_path = self.type_path();
quote!(Option::<#type_path>::decode_value(reader, header)?)
}
pub fn encoder(self, binding: &TokenStream) -> TokenStream {
let type_path = self.type_path();
quote!(<#type_path>::try_from(#binding)?)
}
pub fn type_path(self) -> TokenStream {
match self {
Asn1Type::BitString => quote!(::der::asn1::BitStringRef),
Asn1Type::Ia5String => quote!(::der::asn1::Ia5StringRef),
Asn1Type::GeneralizedTime => quote!(::der::asn1::GeneralizedTime),
Asn1Type::OctetString => quote!(&::der::asn1::OctetStringRef),
Asn1Type::PrintableString => quote!(::der::asn1::PrintableStringRef),
Asn1Type::TeletexString => quote!(::der::asn1::TeletexStringRef),
Asn1Type::VideotexString => quote!(::der::asn1::VideotexStringRef),
Asn1Type::UtcTime => quote!(::der::asn1::UtcTime),
Asn1Type::Utf8String => quote!(::der::asn1::Utf8StringRef),
Asn1Type::BmpString => quote!(::der::asn1::BmpString),
}
}
}
impl FromStr for Asn1Type {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, ParseError> {
match s {
"BIT STRING" => Ok(Self::BitString),
"IA5String" => Ok(Self::Ia5String),
"GeneralizedTime" => Ok(Self::GeneralizedTime),
"OCTET STRING" => Ok(Self::OctetString),
"PrintableString" => Ok(Self::PrintableString),
"TeletexString" => Ok(Self::TeletexString),
"VideotexString" => Ok(Self::VideotexString),
"UTCTime" => Ok(Self::UtcTime),
"UTF8String" => Ok(Self::Utf8String),
"BMPString" => Ok(Self::BmpString),
_ => Err(ParseError),
}
}
}
impl fmt::Display for Asn1Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Asn1Type::BitString => "BIT STRING",
Asn1Type::Ia5String => "IA5String",
Asn1Type::GeneralizedTime => "GeneralizedTime",
Asn1Type::OctetString => "OCTET STRING",
Asn1Type::PrintableString => "PrintableString",
Asn1Type::TeletexString => "TeletexString",
Asn1Type::VideotexString => "VideotexString",
Asn1Type::UtcTime => "UTCTime",
Asn1Type::Utf8String => "UTF8String",
Asn1Type::BmpString => "BMPString",
})
}
}
#[derive(Debug)]
pub(crate) struct ParseError;