1use crate::Asn1Type;
4use proc_macro2::TokenStream;
5use quote::quote;
6use std::{
7 fmt::{self, Display},
8 str::FromStr,
9};
10
11#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
13pub(crate) enum Tag {
14 Universal(Asn1Type),
16
17 ContextSpecific {
19 constructed: bool,
21
22 number: TagNumber,
24 },
25}
26
27impl Tag {
28 pub fn to_tokens(self) -> TokenStream {
30 match self {
31 Tag::Universal(ty) => ty.tag(),
32 Tag::ContextSpecific {
33 constructed,
34 number,
35 } => {
36 let constructed = if constructed {
37 quote!(true)
38 } else {
39 quote!(false)
40 };
41
42 let number = number.to_tokens();
43
44 quote! {
45 ::der::Tag::ContextSpecific {
46 constructed: #constructed,
47 number: #number,
48 }
49 }
50 }
51 }
52 }
53}
54
55#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
57pub(crate) enum TagMode {
58 #[default]
62 Explicit,
63
64 Implicit,
68}
69
70impl TagMode {
71 pub fn to_tokens(self) -> TokenStream {
74 match self {
75 TagMode::Explicit => quote!(::der::TagMode::Explicit),
76 TagMode::Implicit => quote!(::der::TagMode::Implicit),
77 }
78 }
79}
80
81impl FromStr for TagMode {
82 type Err = ParseError;
83
84 fn from_str(s: &str) -> Result<Self, ParseError> {
85 match s {
86 "EXPLICIT" | "explicit" => Ok(TagMode::Explicit),
87 "IMPLICIT" | "implicit" => Ok(TagMode::Implicit),
88 _ => Err(ParseError),
89 }
90 }
91}
92
93impl Display for TagMode {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self {
96 TagMode::Explicit => f.write_str("EXPLICIT"),
97 TagMode::Implicit => f.write_str("IMPLICIT"),
98 }
99 }
100}
101
102#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
104pub(crate) struct TagNumber(pub u8);
105
106impl TagNumber {
107 pub const MAX: u8 = 30;
109
110 pub fn to_tokens(self) -> TokenStream {
112 match self.0 {
113 0 => quote!(::der::TagNumber::N0),
114 1 => quote!(::der::TagNumber::N1),
115 2 => quote!(::der::TagNumber::N2),
116 3 => quote!(::der::TagNumber::N3),
117 4 => quote!(::der::TagNumber::N4),
118 5 => quote!(::der::TagNumber::N5),
119 6 => quote!(::der::TagNumber::N6),
120 7 => quote!(::der::TagNumber::N7),
121 8 => quote!(::der::TagNumber::N8),
122 9 => quote!(::der::TagNumber::N9),
123 10 => quote!(::der::TagNumber::N10),
124 11 => quote!(::der::TagNumber::N11),
125 12 => quote!(::der::TagNumber::N12),
126 13 => quote!(::der::TagNumber::N13),
127 14 => quote!(::der::TagNumber::N14),
128 15 => quote!(::der::TagNumber::N15),
129 16 => quote!(::der::TagNumber::N16),
130 17 => quote!(::der::TagNumber::N17),
131 18 => quote!(::der::TagNumber::N18),
132 19 => quote!(::der::TagNumber::N19),
133 20 => quote!(::der::TagNumber::N20),
134 21 => quote!(::der::TagNumber::N21),
135 22 => quote!(::der::TagNumber::N22),
136 23 => quote!(::der::TagNumber::N23),
137 24 => quote!(::der::TagNumber::N24),
138 25 => quote!(::der::TagNumber::N25),
139 26 => quote!(::der::TagNumber::N26),
140 27 => quote!(::der::TagNumber::N27),
141 28 => quote!(::der::TagNumber::N28),
142 29 => quote!(::der::TagNumber::N29),
143 30 => quote!(::der::TagNumber::N30),
144 _ => unreachable!("tag number out of range: {}", self),
145 }
146 }
147}
148
149impl FromStr for TagNumber {
150 type Err = ParseError;
151
152 fn from_str(s: &str) -> Result<Self, ParseError> {
153 let n = s.parse::<u8>().map_err(|_| ParseError)?;
154
155 if n <= Self::MAX {
156 Ok(Self(n))
157 } else {
158 Err(ParseError)
159 }
160 }
161}
162
163impl Display for TagNumber {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 write!(f, "{}", self.0)
166 }
167}
168
169#[derive(Debug)]
171pub(crate) struct ParseError;