1macro_rules! impl_any_conversions {
2 ($type: ty) => {
3 impl_any_conversions!($type, );
4 };
5 ($type: ty, $($li: lifetime)?) => {
6 impl<'__der: $($li),*, $($li),*> TryFrom<$crate::AnyRef<'__der>> for $type {
7 type Error = $crate::Error;
8
9 fn try_from(any: $crate::AnyRef<'__der>) -> $crate::Result<$type> {
10 any.decode_as()
11 }
12 }
13
14 #[cfg(feature = "alloc")]
15 impl<'__der: $($li),*, $($li),*> TryFrom<&'__der $crate::Any> for $type {
16 type Error = $crate::Error;
17
18 fn try_from(any: &'__der $crate::Any) -> $crate::Result<$type> {
19 any.decode_as()
20 }
21 }
22 };
23}
24
25macro_rules! impl_string_type {
26 ($type: ty, $($li: lifetime)?) => {
27 impl_any_conversions!($type, $($li),*);
28
29 mod __impl_string {
30 use super::*;
31
32 use crate::{
33 ord::OrdIsValueOrd, BytesRef, DecodeValue, EncodeValue, Header, Length, Reader,
34 Result, Writer,
35 };
36 use core::{fmt, str};
37
38 impl<$($li),*> AsRef<str> for $type {
39 fn as_ref(&self) -> &str {
40 self.as_str()
41 }
42 }
43
44 impl<$($li),*> AsRef<[u8]> for $type {
45 fn as_ref(&self) -> &[u8] {
46 self.as_bytes()
47 }
48 }
49
50 impl<'__der: $($li),*, $($li),*> DecodeValue<'__der> for $type {
51 type Error = $crate::Error;
52
53 fn decode_value<R: Reader<'__der>>(reader: &mut R, header: Header) -> $crate::Result<Self> {
54 Self::new(<&'__der BytesRef>::decode_value(reader, header)?.as_slice())
55 }
56 }
57
58 impl<$($li),*> EncodeValue for $type {
59 fn value_len(&self) -> Result<Length> {
60 self.inner.value_len()
61 }
62
63 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
64 self.inner.encode_value(writer)
65 }
66 }
67
68 impl<$($li),*> OrdIsValueOrd for $type {}
69
70 impl<$($li),*> fmt::Display for $type {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 f.write_str(self.as_str())
73 }
74 }
75 }
76 };
77}
78
79macro_rules! impl_custom_class {
80 ($class_type_name: ident, $class_enum_name: ident, $asn1_class_name: literal, $class_bits_str: literal) => {
81 #[doc = concat!("`", $asn1_class_name, "` field which wraps an owned inner value.")]
82 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
86 pub struct $class_type_name<T> {
87 #[doc = concat!("`", $asn1_class_name, "` tag number sans the leading `", $class_bits_str, "` class")]
88 pub tag_number: TagNumber,
90
91 pub tag_mode: TagMode,
93
94 pub value: T,
96 }
97
98 impl<T> $class_type_name<T> {
99 #[doc = concat!("Attempt to decode an `EXPLICIT` ASN.1 `", $asn1_class_name, "` field with the")]
100 #[doc = concat!("- Returns `Ok(None)` if class other than [`Class::", stringify!($class_enum_name), "`] tag")]
108 pub fn decode_explicit<'a, R: Reader<'a>>(
115 reader: &mut R,
116 tag_number: TagNumber,
117 ) -> Result<Option<Self>, T::Error>
118 where
119 T: Decode<'a>,
120 {
121 if !Tag::peek_matches(reader, Class::$class_enum_name, tag_number)? {
122 return Ok(None);
123 }
124 Ok(Some(Self::decode(reader)?))
125 }
126
127 #[doc = concat!("Attempt to decode an `IMPLICIT` ASN.1 `", $asn1_class_name, "` field with the")]
128 pub fn decode_implicit<'a, R: Reader<'a>>(
141 reader: &mut R,
142 tag_number: TagNumber,
143 ) -> Result<Option<Self>, T::Error>
144 where
145 T: DecodeValue<'a> + IsConstructed,
146 {
147 if !Tag::peek_matches(reader, Class::$class_enum_name, tag_number)? {
149 return Ok(None);
150 }
151
152 let header = Header::decode(reader)?;
154
155 if header.tag().is_constructed() != T::CONSTRUCTED
157 && reader.encoding_rules().is_der() {
158 return Err(reader.error(header.tag().non_canonical_error()).into());
159 }
160
161 let value = crate::reader::read_value(reader, header, T::decode_value)?;
163
164 Ok(Some(Self {
165 tag_number,
166 tag_mode: TagMode::Implicit,
167 value,
168 }))
169 }
170 }
171
172 impl<'a, T> Choice<'a> for $class_type_name<T>
173 where
174 T: Decode<'a> + Tagged,
175 {
176 fn can_decode(tag: Tag) -> bool {
177 tag.class() == Class::$class_enum_name
178 }
179 }
180
181 impl<'a, T> Decode<'a> for $class_type_name<T>
182 where
183 T: Decode<'a>,
184 {
185 type Error = T::Error;
186
187 fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self, Self::Error> {
188 let header = Header::decode(reader)?;
190
191 if !header.tag().is_constructed() {
193 return Err(reader.error(header.tag().non_canonical_error()).into());
194 }
195 match header.tag() {
196 Tag::$class_enum_name { number, .. } => Ok(Self {
197 tag_number: number,
198 tag_mode: TagMode::default(),
199 value: crate::reader::read_value(reader, header, |reader, _| {
200 T::decode(reader)
202 })?,
203 }),
204 tag => Err(reader.error(tag.unexpected_error(None)).into())
205 }
206 }
207 }
208
209 impl<T> EncodeValue for $class_type_name<T>
210 where
211 T: EncodeValue + Tagged,
212 {
213 fn value_len(&self) -> Result<Length, Error> {
214 match self.tag_mode {
215 TagMode::Explicit => self.value.encoded_len(),
216 TagMode::Implicit => self.value.value_len(),
217 }
218 }
219
220 fn encode_value(&self, writer: &mut impl Writer) -> Result<(), Error> {
221 match self.tag_mode {
222 TagMode::Explicit => self.value.encode(writer),
223 TagMode::Implicit => self.value.encode_value(writer),
224 }
225 }
226 }
227
228 impl<T> Tagged for $class_type_name<T>
229 where
230 T: Tagged,
231 {
232 fn tag(&self) -> Tag {
233 let constructed = match self.tag_mode {
234 TagMode::Explicit => true,
238
239 TagMode::Implicit => self.value.tag().is_constructed(),
246 };
247
248 Tag::$class_enum_name {
249 number: self.tag_number,
250 constructed,
251 }
252 }
253 }
254
255 impl<'a, T> TryFrom<AnyRef<'a>> for $class_type_name<T>
256 where
257 T: Decode<'a>,
258 {
259 type Error = T::Error;
260
261 fn try_from(any: AnyRef<'a>) -> Result<$class_type_name<T>, Self::Error> {
262 match any.tag() {
263 Tag::$class_enum_name {
264 number,
265 constructed: true,
266 } => Ok(Self {
267 tag_number: number,
268 tag_mode: TagMode::default(),
269 value: T::from_der(any.value())?,
270 }),
271 tag => Err(tag.unexpected_error(None).to_error().into()),
272 }
273 }
274 }
275
276 impl<T> ValueOrd for $class_type_name<T>
277 where
278 T: EncodeValue + ValueOrd + Tagged,
279 {
280 fn value_cmp(&self, other: &Self) -> Result<Ordering, Error> {
281 match self.tag_mode {
282 TagMode::Explicit => self.der_cmp(other),
283 TagMode::Implicit => self.value_cmp(other),
284 }
285 }
286 }
287 };
288}
289
290macro_rules! impl_custom_class_ref {
291 ($ref_class_type_name: ident, $class_type_name: ident, $asn1_class_name: literal, $class_bits_str: literal) => {
292 #[doc = concat!("`", $asn1_class_name, "` field reference.")]
293 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
298 pub struct $ref_class_type_name<'a, T> {
299 #[doc = concat!("`", $asn1_class_name, "` tag number sans the leading `", $class_bits_str, "` class")]
300 pub tag_number: TagNumber,
302
303 pub tag_mode: TagMode,
305
306 pub value: &'a T,
308 }
309
310 impl<'a, T> $ref_class_type_name<'a, T> {
311 fn encoder(&self) -> $class_type_name<EncodeValueRef<'a, T>> {
313 $class_type_name {
314 tag_number: self.tag_number,
315 tag_mode: self.tag_mode,
316 value: EncodeValueRef(self.value),
317 }
318 }
319 }
320
321 impl<T> EncodeValue for $ref_class_type_name<'_, T>
322 where
323 T: EncodeValue + Tagged,
324 {
325 fn value_len(&self) -> Result<Length, Error> {
326 self.encoder().value_len()
327 }
328
329 fn encode_value(&self, writer: &mut impl Writer) -> Result<(), Error> {
330 self.encoder().encode_value(writer)
331 }
332 }
333
334 impl<T> Tagged for $ref_class_type_name<'_, T>
335 where
336 T: Tagged,
337 {
338 fn tag(&self) -> Tag {
339 self.encoder().tag()
340 }
341 }
342 };
343}