Skip to main content

rasn/avn/
de.rs

1//! Decoding ASN.1 Value Notation (AVN) text into Rust structures.
2//!
3//! 1. **Parse** the entire input string into an [`AvnValue`] tree using nom combinators.
4//! 2. **Type-directed decode** pops values from a stack and dispatches.
5
6#![deny(clippy::all)]
7
8use alloc::collections::BTreeMap;
9use core::str::FromStr;
10use nom::{
11    IResult,
12    branch::alt,
13    bytes::complete::{take_while, take_while1},
14    character::complete::{char, digit1, multispace0},
15    combinator::{map, opt, recognize},
16    sequence::{pair, preceded},
17};
18use num_bigint::BigInt;
19
20use crate::{
21    Decode,
22    de::Error,
23    error::{AvnDecodeErrorKind, DecodeError},
24    types::{
25        Any, BitString, BmpString, Constraints, Constructed, Date, DecodeChoice, Enumerated,
26        GeneralString, GeneralizedTime, GraphicString, Ia5String, NumericString, ObjectIdentifier,
27        Oid, PrintableString, SetOf, Tag, TeletexString, UtcTime, Utf8String, VisibleString,
28        variants,
29    },
30};
31
32use super::value::AvnValue;
33
34// ---------------------------------------------------------------------------
35// nom-based parser
36// ---------------------------------------------------------------------------
37
38fn parse_identifier_str(input: &str) -> IResult<&str, &str> {
39    recognize(pair(
40        take_while1(|c: char| c.is_ascii_alphabetic()),
41        take_while(|c: char| c.is_ascii_alphanumeric() || c == '-' || c == '_'),
42    ))(input)
43}
44
45fn parse_hex_or_bin_string(input: &str) -> IResult<&str, AvnValue> {
46    let (input, _) = char('\'')(input)?;
47    let (input, raw) = take_while(|c: char| c != '\'')(input)?;
48    let (input, _) = char('\'')(input)?;
49    let content: alloc::string::String = raw.chars().filter(|c| !c.is_whitespace()).collect();
50    let (input, suffix) = alt((char('H'), char('B')))(input)?;
51    if suffix == 'H' {
52        parse_hex_bytes(&content)
53            .map(|bytes| (input, AvnValue::OctetString(bytes)))
54            .ok_or_else(|| {
55                nom::Err::Error(nom::error::Error::new(
56                    input,
57                    nom::error::ErrorKind::HexDigit,
58                ))
59            })
60    } else {
61        parse_bin_bits(&content)
62            .map(|(bytes, bit_length)| (input, AvnValue::BitString { bytes, bit_length }))
63            .ok_or_else(|| {
64                nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit))
65            })
66    }
67}
68
69fn parse_quoted_string(input: &str) -> IResult<&str, AvnValue> {
70    let (input, _) = char('"')(input)?;
71    let mut s = alloc::string::String::new();
72    let mut rest = input;
73    loop {
74        match rest.chars().next() {
75            None => {
76                return Err(nom::Err::Error(nom::error::Error::new(
77                    rest,
78                    nom::error::ErrorKind::Eof,
79                )));
80            }
81            Some('"') => {
82                rest = &rest[1..];
83                if rest.starts_with('"') {
84                    s.push('"');
85                    rest = &rest[1..];
86                } else {
87                    break;
88                }
89            }
90            Some(c) => {
91                s.push(c);
92                rest = &rest[c.len_utf8()..];
93            }
94        }
95    }
96    Ok((rest, AvnValue::CharString(s)))
97}
98
99fn parse_number(input: &str) -> IResult<&str, AvnValue> {
100    map(
101        recognize(pair(
102            opt(char('-')),
103            pair(digit1, opt(preceded(char('.'), digit1))),
104        )),
105        |s: &str| {
106            if s.contains('.') {
107                AvnValue::Real(s.into())
108            } else {
109                AvnValue::Integer(s.into())
110            }
111        },
112    )(input)
113}
114
115fn parse_value(input: &str) -> IResult<&str, AvnValue> {
116    parse_value_depth(input, 0)
117}
118
119fn parse_value_depth(input: &str, depth: usize) -> IResult<&str, AvnValue> {
120    if depth > 64 {
121        return Err(nom::Err::Failure(nom::error::Error::new(
122            input,
123            nom::error::ErrorKind::TooLarge,
124        )));
125    }
126    let (input, _) = multispace0(input)?;
127    alt((
128        parse_hex_or_bin_string,
129        parse_quoted_string,
130        parse_number,
131        move |i| parse_brace(i, depth + 1),
132        move |i| parse_identifier_or_choice(i, depth),
133    ))(input)
134}
135
136fn parse_identifier_or_choice(input: &str, depth: usize) -> IResult<&str, AvnValue> {
137    let (after_id, id) = parse_identifier_str(input)?;
138    let (after_ws, _) = multispace0(after_id)?;
139    if let Some(rest) = after_ws.strip_prefix(':') {
140        let (rest, inner) = parse_value_depth(rest, depth + 1)?;
141        return Ok((
142            rest,
143            AvnValue::Choice {
144                identifier: id.into(),
145                value: alloc::boxed::Box::new(inner),
146            },
147        ));
148    }
149    let val = match id {
150        "TRUE" => AvnValue::Boolean(true),
151        "FALSE" => AvnValue::Boolean(false),
152        "NULL" => AvnValue::Null,
153        "PLUS-INFINITY" | "MINUS-INFINITY" | "NOT-A-NUMBER" => AvnValue::Real(id.into()),
154        _ => AvnValue::Enumerated(id.into()),
155    };
156    Ok((after_id, val))
157}
158
159fn parse_brace(input: &str, depth: usize) -> IResult<&str, AvnValue> {
160    let (input, _) = char('{')(input)?;
161    let (input, _) = multispace0(input)?;
162
163    if let Ok((rest, _)) = char::<_, nom::error::Error<&str>>('}')(input) {
164        return Ok((rest, AvnValue::SequenceOf(alloc::vec![])));
165    }
166
167    enum BraceItem {
168        Named(alloc::string::String, AvnValue),
169        Bare(AvnValue),
170    }
171
172    let mut items: alloc::vec::Vec<BraceItem> = alloc::vec![];
173    let mut current = input;
174
175    loop {
176        let (after_ws, _) = multispace0(current)?;
177        current = after_ws;
178
179        if let Ok((after_id, id)) = parse_identifier_str(current) {
180            let (after_ws2, _) = multispace0(after_id)?;
181            if let Some(after_colon) = after_ws2.strip_prefix(':') {
182                // CHOICE element inside braces: id : value
183                let (rest, val) = parse_value_depth(after_colon, depth)?;
184                items.push(BraceItem::Bare(AvnValue::Choice {
185                    identifier: id.into(),
186                    value: alloc::boxed::Box::new(val),
187                }));
188                current = rest;
189            } else if after_ws2.starts_with(',') || after_ws2.starts_with('}') {
190                // Bare identifier: enumerated or real keyword
191                let val = match id {
192                    "PLUS-INFINITY" | "MINUS-INFINITY" | "NOT-A-NUMBER" => {
193                        AvnValue::Real(id.into())
194                    }
195                    _ => AvnValue::Enumerated(id.into()),
196                };
197                items.push(BraceItem::Bare(val));
198                current = after_id;
199            } else {
200                // Named SEQUENCE field: id value
201                let (rest, val) = parse_value_depth(after_ws2, depth)?;
202                items.push(BraceItem::Named(id.into(), val));
203                current = rest;
204            }
205        } else {
206            // Non-identifier bare value (number, hex/bin string, nested brace, …)
207            let (rest, val) = parse_value_depth(current, depth)?;
208            items.push(BraceItem::Bare(val));
209            current = rest;
210        }
211
212        let (after_sep, _) = multispace0(current)?;
213        current = after_sep;
214
215        if current.starts_with('}') {
216            current = &current[1..];
217            break;
218        } else if current.starts_with(',') {
219            current = &current[1..];
220        } else if current
221            .chars()
222            .next()
223            .is_some_and(|c| c.is_ascii_digit() || c == '-')
224            && items
225                .iter()
226                .all(|i| matches!(i, BraceItem::Bare(AvnValue::Integer(_))))
227        {
228            // OID-style space-separated arcs — no comma needed, continue
229        } else {
230            return Err(nom::Err::Error(nom::error::Error::new(
231                current,
232                nom::error::ErrorKind::Char,
233            )));
234        }
235    }
236
237    let has_named = items.iter().any(|i| matches!(i, BraceItem::Named(..)));
238    let has_bare = items.iter().any(|i| matches!(i, BraceItem::Bare(..)));
239
240    if has_named && has_bare {
241        return Err(nom::Err::Error(nom::error::Error::new(
242            current,
243            nom::error::ErrorKind::Verify,
244        )));
245    }
246
247    if has_named {
248        Ok((
249            current,
250            AvnValue::Sequence(
251                items
252                    .into_iter()
253                    .map(|item| {
254                        if let BraceItem::Named(name, val) = item {
255                            (name, Some(val))
256                        } else {
257                            unreachable!()
258                        }
259                    })
260                    .collect(),
261            ),
262        ))
263    } else {
264        Ok((
265            current,
266            AvnValue::SequenceOf(
267                items
268                    .into_iter()
269                    .map(|item| {
270                        if let BraceItem::Bare(val) = item {
271                            val
272                        } else {
273                            unreachable!()
274                        }
275                    })
276                    .collect(),
277            ),
278        ))
279    }
280}
281
282// ---------------------------------------------------------------------------
283// Low-level string helpers
284// ---------------------------------------------------------------------------
285
286fn parse_hex_bytes(hex: &str) -> Option<alloc::vec::Vec<u8>> {
287    if hex.is_empty() {
288        return Some(alloc::vec![]);
289    }
290    if !hex.len().is_multiple_of(2) {
291        return None;
292    }
293    let b = hex.as_bytes();
294    let mut out = alloc::vec::Vec::with_capacity(hex.len() / 2);
295    for chunk in b.chunks(2) {
296        let hi = nibble(chunk[0])?;
297        let lo = nibble(chunk[1])?;
298        out.push((hi << 4) | lo);
299    }
300    Some(out)
301}
302
303fn nibble(c: u8) -> Option<u8> {
304    match c {
305        b'0'..=b'9' => Some(c - b'0'),
306        b'a'..=b'f' => Some(c - b'a' + 10),
307        b'A'..=b'F' => Some(c - b'A' + 10),
308        _ => None,
309    }
310}
311
312fn parse_bin_bits(bin: &str) -> Option<(alloc::vec::Vec<u8>, usize)> {
313    if bin.is_empty() {
314        return Some((alloc::vec![], 0));
315    }
316    let bit_length = bin.len();
317    let mut bytes: alloc::vec::Vec<u8> = alloc::vec![];
318    let mut current: u8 = 0;
319    for (i, c) in bin.chars().enumerate() {
320        let bit: u8 = match c {
321            '0' => 0,
322            '1' => 1,
323            _ => return None,
324        };
325        current |= bit << (7 - (i % 8));
326        if i % 8 == 7 {
327            bytes.push(current);
328            current = 0;
329        }
330    }
331    if !bit_length.is_multiple_of(8) {
332        bytes.push(current);
333    }
334    Some((bytes, bit_length))
335}
336
337// ---------------------------------------------------------------------------
338// Decoder struct
339// ---------------------------------------------------------------------------
340
341macro_rules! decode_avn_value {
342    ($decoder_fn:expr, $stack:expr) => {
343        $stack
344            .pop()
345            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))
346            .and_then(|v| v.ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi())))
347            .and_then($decoder_fn)
348    };
349}
350
351/// Decodes ASN.1 Value Notation text into Rust structures.
352pub struct Decoder {
353    stack: alloc::vec::Vec<Option<AvnValue>>,
354}
355
356impl Decoder {
357    /// Create a new decoder by parsing the entire input string.
358    pub fn new(input: &str) -> Result<Self, DecodeError> {
359        let (rest, root) = parse_value(input).map_err(|e| match e {
360            nom::Err::Incomplete(_) => DecodeError::from(AvnDecodeErrorKind::AvnEndOfInput {}),
361            nom::Err::Error(e) | nom::Err::Failure(e) => {
362                if e.code == nom::error::ErrorKind::TooLarge {
363                    DecodeError::from_kind(
364                        crate::error::DecodeErrorKind::ExceedsMaxParseDepth,
365                        crate::Codec::Avn,
366                    )
367                } else {
368                    DecodeError::from(AvnDecodeErrorKind::UnexpectedToken {
369                        found: e.input.chars().take(20).collect(),
370                    })
371                }
372            }
373        })?;
374        if !rest.trim().is_empty() {
375            return Err(DecodeError::from(AvnDecodeErrorKind::UnexpectedToken {
376                found: rest.into(),
377            }));
378        }
379        Ok(Self {
380            stack: alloc::vec![Some(root)],
381        })
382    }
383}
384
385impl From<AvnValue> for Decoder {
386    fn from(value: AvnValue) -> Self {
387        Self {
388            stack: alloc::vec![Some(value)],
389        }
390    }
391}
392
393impl crate::Decoder for Decoder {
394    type Ok = ();
395    type Error = DecodeError;
396    type AnyDecoder<const R: usize, const E: usize> = Self;
397
398    fn codec(&self) -> crate::Codec {
399        crate::Codec::Avn
400    }
401
402    fn decode_any(&mut self, _tag: Tag) -> Result<Any, Self::Error> {
403        let value = self
404            .stack
405            .pop()
406            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?
407            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?;
408        Ok(Any::new(alloc::format!("{value}").into_bytes()))
409    }
410
411    fn decode_bool(&mut self, _t: Tag) -> Result<bool, Self::Error> {
412        decode_avn_value!(Self::boolean_from_value, self.stack)
413    }
414
415    fn decode_enumerated<E: Enumerated>(&mut self, _t: Tag) -> Result<E, Self::Error> {
416        decode_avn_value!(Self::enumerated_from_value::<E>, self.stack)
417    }
418
419    fn decode_integer<I: crate::types::IntegerType>(
420        &mut self,
421        _t: Tag,
422        _c: Constraints,
423    ) -> Result<I, Self::Error> {
424        decode_avn_value!(Self::integer_from_value::<I>, self.stack)
425    }
426
427    fn decode_real<R: crate::types::RealType>(
428        &mut self,
429        _t: Tag,
430        _c: Constraints,
431    ) -> Result<R, Self::Error> {
432        decode_avn_value!(Self::real_from_value::<R>, self.stack)
433    }
434
435    fn decode_null(&mut self, _t: Tag) -> Result<(), Self::Error> {
436        decode_avn_value!(Self::null_from_value, self.stack)
437    }
438
439    fn decode_object_identifier(&mut self, _t: Tag) -> Result<ObjectIdentifier, Self::Error> {
440        decode_avn_value!(Self::oid_from_value, self.stack)
441    }
442
443    fn decode_bit_string(&mut self, _t: Tag, _c: Constraints) -> Result<BitString, Self::Error> {
444        decode_avn_value!(Self::bit_string_from_value, self.stack)
445    }
446
447    fn decode_octet_string<'buf, T>(
448        &'buf mut self,
449        _: Tag,
450        _c: Constraints,
451    ) -> Result<T, Self::Error>
452    where
453        T: From<alloc::vec::Vec<u8>> + From<&'buf [u8]>,
454    {
455        decode_avn_value!(Self::octet_string_from_value, self.stack).map(T::from)
456    }
457
458    fn decode_utf8_string(&mut self, _t: Tag, _c: Constraints) -> Result<Utf8String, Self::Error> {
459        decode_avn_value!(Self::char_string_from_value, self.stack)
460    }
461
462    fn decode_visible_string(
463        &mut self,
464        _t: Tag,
465        _c: Constraints,
466    ) -> Result<VisibleString, Self::Error> {
467        decode_avn_value!(Self::char_string_from_value, self.stack)?
468            .try_into()
469            .map_err(|e| {
470                DecodeError::string_conversion_failed(
471                    Tag::VISIBLE_STRING,
472                    alloc::format!("{e:?}"),
473                    crate::Codec::Avn,
474                )
475            })
476    }
477
478    fn decode_general_string(
479        &mut self,
480        _t: Tag,
481        _c: Constraints,
482    ) -> Result<GeneralString, Self::Error> {
483        decode_avn_value!(Self::char_string_from_value, self.stack)?
484            .try_into()
485            .map_err(|e| {
486                DecodeError::string_conversion_failed(
487                    Tag::GENERAL_STRING,
488                    alloc::format!("{e:?}"),
489                    crate::Codec::Avn,
490                )
491            })
492    }
493
494    fn decode_graphic_string(
495        &mut self,
496        _t: Tag,
497        _c: Constraints,
498    ) -> Result<GraphicString, Self::Error> {
499        decode_avn_value!(Self::char_string_from_value, self.stack)?
500            .try_into()
501            .map_err(|e| {
502                DecodeError::string_conversion_failed(
503                    Tag::GRAPHIC_STRING,
504                    alloc::format!("{e:?}"),
505                    crate::Codec::Avn,
506                )
507            })
508    }
509
510    fn decode_ia5_string(&mut self, _t: Tag, _c: Constraints) -> Result<Ia5String, Self::Error> {
511        decode_avn_value!(Self::char_string_from_value, self.stack)?
512            .try_into()
513            .map_err(|e| {
514                DecodeError::string_conversion_failed(
515                    Tag::IA5_STRING,
516                    alloc::format!("{e:?}"),
517                    crate::Codec::Avn,
518                )
519            })
520    }
521
522    fn decode_printable_string(
523        &mut self,
524        _t: Tag,
525        _c: Constraints,
526    ) -> Result<PrintableString, Self::Error> {
527        decode_avn_value!(Self::char_string_from_value, self.stack)?
528            .try_into()
529            .map_err(|e| {
530                DecodeError::string_conversion_failed(
531                    Tag::PRINTABLE_STRING,
532                    alloc::format!("{e:?}"),
533                    crate::Codec::Avn,
534                )
535            })
536    }
537
538    fn decode_numeric_string(
539        &mut self,
540        _t: Tag,
541        _c: Constraints,
542    ) -> Result<NumericString, Self::Error> {
543        decode_avn_value!(Self::char_string_from_value, self.stack)?
544            .try_into()
545            .map_err(|e| {
546                DecodeError::string_conversion_failed(
547                    Tag::NUMERIC_STRING,
548                    alloc::format!("{e:?}"),
549                    crate::Codec::Avn,
550                )
551            })
552    }
553
554    fn decode_teletex_string(
555        &mut self,
556        _t: Tag,
557        _c: Constraints,
558    ) -> Result<TeletexString, Self::Error> {
559        todo!()
560    }
561
562    fn decode_bmp_string(&mut self, _t: Tag, _c: Constraints) -> Result<BmpString, Self::Error> {
563        decode_avn_value!(Self::char_string_from_value, self.stack)?
564            .try_into()
565            .map_err(|e| {
566                DecodeError::string_conversion_failed(
567                    Tag::BMP_STRING,
568                    alloc::format!("{e:?}"),
569                    crate::Codec::Avn,
570                )
571            })
572    }
573
574    fn decode_explicit_prefix<D: Decode>(&mut self, _t: Tag) -> Result<D, Self::Error> {
575        D::decode(self)
576    }
577
578    fn decode_optional_with_explicit_prefix<D: Decode>(
579        &mut self,
580        _: Tag,
581    ) -> Result<Option<D>, Self::Error> {
582        self.decode_optional()
583    }
584
585    fn decode_utc_time(&mut self, _t: Tag) -> Result<UtcTime, Self::Error> {
586        decode_avn_value!(Self::utc_time_from_value, self.stack)
587    }
588
589    fn decode_generalized_time(&mut self, _t: Tag) -> Result<GeneralizedTime, Self::Error> {
590        decode_avn_value!(Self::generalized_time_from_value, self.stack)
591    }
592
593    fn decode_date(&mut self, _t: Tag) -> Result<Date, Self::Error> {
594        decode_avn_value!(Self::date_from_value, self.stack)
595    }
596
597    fn decode_sequence<const RC: usize, const EC: usize, D, DF, F>(
598        &mut self,
599        _: Tag,
600        _: Option<DF>,
601        decode_fn: F,
602    ) -> Result<D, Self::Error>
603    where
604        D: Constructed<RC, EC>,
605        DF: FnOnce() -> D,
606        F: FnOnce(&mut Self::AnyDecoder<RC, EC>) -> Result<D, Self::Error>,
607    {
608        let last = self
609            .stack
610            .pop()
611            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?
612            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?;
613
614        let mut field_map: BTreeMap<alloc::string::String, AvnValue> = match last {
615            AvnValue::Sequence(fields) => fields
616                .into_iter()
617                .filter_map(|(k, v)| v.map(|v| (k, v)))
618                .collect(),
619            AvnValue::SequenceOf(items) if items.is_empty() => BTreeMap::new(),
620            other => {
621                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
622                    needed: "sequence",
623                    found: alloc::format!("{other:?}"),
624                }));
625            }
626        };
627
628        // Push field values in reverse order so pop() yields them in declaration order.
629        let mut field_names: alloc::vec::Vec<&str> = D::FIELDS.iter().map(|f| f.name).collect();
630        if let Some(extended_fields) = D::EXTENDED_FIELDS {
631            field_names.extend(extended_fields.iter().map(|f| f.name));
632        }
633        field_names.reverse();
634        for name in field_names {
635            self.stack.push(field_map.remove(name));
636        }
637        (decode_fn)(self)
638    }
639
640    fn decode_sequence_of<D: Decode>(
641        &mut self,
642        _t: Tag,
643        _c: Constraints,
644    ) -> Result<alloc::vec::Vec<D>, Self::Error> {
645        decode_avn_value!(|v| self.sequence_of_from_value(v), self.stack)
646    }
647
648    fn decode_set_of<D: Decode + Eq + core::hash::Hash>(
649        &mut self,
650        _t: Tag,
651        _c: Constraints,
652    ) -> Result<SetOf<D>, Self::Error> {
653        decode_avn_value!(|v| self.set_of_from_value(v), self.stack)
654    }
655
656    fn decode_set<const RC: usize, const EC: usize, FIELDS, SET, D, F>(
657        &mut self,
658        _t: Tag,
659        decode_fn: D,
660        field_fn: F,
661    ) -> Result<SET, Self::Error>
662    where
663        SET: Decode + Constructed<RC, EC>,
664        FIELDS: Decode,
665        D: Fn(&mut Self::AnyDecoder<RC, EC>, usize, Tag) -> Result<FIELDS, Self::Error>,
666        F: FnOnce(alloc::vec::Vec<FIELDS>) -> Result<SET, Self::Error>,
667    {
668        let last = self
669            .stack
670            .pop()
671            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?
672            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?;
673
674        let mut field_map: BTreeMap<alloc::string::String, AvnValue> = match last {
675            AvnValue::Sequence(fields) => fields
676                .into_iter()
677                .filter_map(|(k, v)| v.map(|v| (k, v)))
678                .collect(),
679            AvnValue::SequenceOf(items) if items.is_empty() => BTreeMap::new(),
680            other => {
681                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
682                    needed: "set",
683                    found: alloc::format!("{other:?}"),
684                }));
685            }
686        };
687
688        let mut fields_out = alloc::vec![];
689
690        let mut field_indices: alloc::vec::Vec<(usize, _)> =
691            SET::FIELDS.iter().enumerate().collect();
692        field_indices
693            .sort_by(|(_, a), (_, b)| a.tag_tree.smallest_tag().cmp(&b.tag_tree.smallest_tag()));
694        for (index, field) in field_indices {
695            self.stack.push(field_map.remove(field.name));
696            fields_out.push((decode_fn)(self, index, field.tag)?);
697        }
698        for (index, field) in SET::EXTENDED_FIELDS
699            .iter()
700            .flat_map(|fields| fields.iter())
701            .enumerate()
702        {
703            self.stack.push(field_map.remove(field.name));
704            fields_out.push((decode_fn)(self, index + SET::FIELDS.len(), field.tag)?);
705        }
706        (field_fn)(fields_out)
707    }
708
709    fn decode_choice<D>(&mut self, _c: Constraints) -> Result<D, Self::Error>
710    where
711        D: DecodeChoice,
712    {
713        decode_avn_value!(|v| self.choice_from_value::<D>(v), self.stack)
714    }
715
716    fn decode_optional<D: Decode>(&mut self) -> Result<Option<D>, Self::Error> {
717        match self
718            .stack
719            .pop()
720            .ok_or_else(|| DecodeError::from(AvnDecodeErrorKind::eoi()))?
721        {
722            None => Ok(None),
723            Some(v) => {
724                self.stack.push(Some(v));
725                Some(D::decode(self)).transpose()
726            }
727        }
728    }
729
730    fn decode_optional_with_tag<D: Decode>(&mut self, _: Tag) -> Result<Option<D>, Self::Error> {
731        self.decode_optional()
732    }
733
734    fn decode_optional_with_constraints<D: Decode>(
735        &mut self,
736        _: Constraints,
737    ) -> Result<Option<D>, Self::Error> {
738        self.decode_optional()
739    }
740
741    fn decode_optional_with_tag_and_constraints<D: Decode>(
742        &mut self,
743        _t: Tag,
744        _c: Constraints,
745    ) -> Result<Option<D>, Self::Error> {
746        self.decode_optional()
747    }
748
749    fn decode_extension_addition_with_explicit_tag_and_constraints<D: Decode>(
750        &mut self,
751        tag: Tag,
752        constraints: Constraints,
753    ) -> Result<Option<D>, Self::Error> {
754        self.decode_extension_addition_with_tag_and_constraints::<D>(tag, constraints)
755    }
756
757    fn decode_extension_addition_with_tag_and_constraints<D: Decode>(
758        &mut self,
759        _: Tag,
760        _: Constraints,
761    ) -> Result<Option<D>, Self::Error> {
762        self.decode_optional()
763    }
764
765    fn decode_extension_addition_group<
766        const RC: usize,
767        const EC: usize,
768        D: Decode + Constructed<RC, EC>,
769    >(
770        &mut self,
771    ) -> Result<Option<D>, Self::Error> {
772        self.decode_optional()
773    }
774}
775
776// ---------------------------------------------------------------------------
777// Helper methods on Decoder
778// ---------------------------------------------------------------------------
779
780impl Decoder {
781    fn boolean_from_value(value: AvnValue) -> Result<bool, DecodeError> {
782        match value {
783            AvnValue::Boolean(b) => Ok(b),
784            other => Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
785                needed: "boolean",
786                found: alloc::format!("{other:?}"),
787            })),
788        }
789    }
790
791    fn enumerated_from_value<E: Enumerated>(value: AvnValue) -> Result<E, DecodeError> {
792        let id = match value {
793            AvnValue::Enumerated(id) => id,
794            other => {
795                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
796                    needed: "enumerated identifier",
797                    found: alloc::format!("{other:?}"),
798                }));
799            }
800        };
801        E::from_identifier(&id).ok_or_else(|| {
802            DecodeError::from(AvnDecodeErrorKind::AvnInvalidEnumDiscriminant { discriminant: id })
803        })
804    }
805
806    fn integer_from_value<I: crate::types::IntegerType>(value: AvnValue) -> Result<I, DecodeError> {
807        let s = match value {
808            AvnValue::Integer(s) => s,
809            other => {
810                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
811                    needed: "integer",
812                    found: alloc::format!("{other:?}"),
813                }));
814            }
815        };
816        let bigint = BigInt::from_str(&s).map_err(|e| {
817            DecodeError::from(AvnDecodeErrorKind::IntegerParseError {
818                msg: alloc::format!("{e}"),
819            })
820        })?;
821        I::try_from(bigint).map_err(|_| DecodeError::integer_overflow(I::WIDTH, crate::Codec::Avn))
822    }
823
824    fn real_from_value<R: crate::types::RealType>(value: AvnValue) -> Result<R, DecodeError> {
825        let s: alloc::string::String = match value {
826            AvnValue::Real(s) => s,
827            AvnValue::Integer(s) => s, // handles "-0" which lexes as Number("-0")
828            AvnValue::Enumerated(s) => s, // handles PLUS-INFINITY etc. if missed as Identifier
829            other => {
830                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
831                    needed: "real",
832                    found: alloc::format!("{other:?}"),
833                }));
834            }
835        };
836
837        let real_err = || {
838            DecodeError::from_kind(
839                crate::error::DecodeErrorKind::InvalidRealEncoding,
840                crate::Codec::Avn,
841            )
842        };
843
844        match s.as_str() {
845            "PLUS-INFINITY" => {
846                return R::try_from_float(f64::INFINITY).ok_or_else(real_err);
847            }
848            "MINUS-INFINITY" => {
849                return R::try_from_float(f64::NEG_INFINITY).ok_or_else(real_err);
850            }
851            "NOT-A-NUMBER" => {
852                return R::try_from_float(f64::NAN).ok_or_else(real_err);
853            }
854            "-0" => {
855                return R::try_from_float(-0.0_f64).ok_or_else(real_err);
856            }
857            _ => {}
858        }
859
860        let f: f64 = s.parse().map_err(|_| real_err())?;
861        R::try_from_float(f).ok_or_else(real_err)
862    }
863
864    fn null_from_value(value: AvnValue) -> Result<(), DecodeError> {
865        match value {
866            AvnValue::Null => Ok(()),
867            other => Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
868                needed: "null",
869                found: alloc::format!("{other:?}"),
870            })),
871        }
872    }
873
874    fn oid_from_value(value: AvnValue) -> Result<ObjectIdentifier, DecodeError> {
875        // OID is encoded as { arc1 arc2 ... } which parses as SequenceOf([Integer, ...])
876        let arcs: alloc::vec::Vec<u32> = match value {
877            AvnValue::Oid(arcs) => arcs,
878            AvnValue::SequenceOf(items) => items
879                .into_iter()
880                .map(|item| match item {
881                    AvnValue::Integer(s) => s.parse::<u32>().map_err(|_| {
882                        DecodeError::from(AvnDecodeErrorKind::InvalidOid { value: s })
883                    }),
884                    other => Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
885                        needed: "OID arc (integer)",
886                        found: alloc::format!("{other:?}"),
887                    })),
888                })
889                .collect::<Result<_, _>>()?,
890            other => {
891                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
892                    needed: "OID as { arc... }",
893                    found: alloc::format!("{other:?}"),
894                }));
895            }
896        };
897        Oid::new(&arcs).map(ObjectIdentifier::from).ok_or_else(|| {
898            DecodeError::from(AvnDecodeErrorKind::InvalidOid {
899                value: alloc::format!("{arcs:?}"),
900            })
901        })
902    }
903
904    fn bit_string_from_value(value: AvnValue) -> Result<BitString, DecodeError> {
905        let (bytes, bit_length) = match value {
906            AvnValue::BitString { bytes, bit_length } => (bytes, bit_length),
907            // Hex notation '...'H also used for byte-aligned bit strings
908            AvnValue::OctetString(bytes) => {
909                let bl = bytes.len() * 8;
910                (bytes, bl)
911            }
912            other => {
913                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
914                    needed: "bit string ('...'H or '...'B)",
915                    found: alloc::format!("{other:?}"),
916                }));
917            }
918        };
919        // Build BitVec from raw bytes and trim to exact bit_length
920        let mut bv = BitString::try_from_vec(bytes).map_err(|e| {
921            DecodeError::custom(
922                alloc::format!("Failed to create BitString: {e:02x?}"),
923                crate::Codec::Avn,
924            )
925        })?;
926        while bv.len() > bit_length {
927            bv.pop();
928        }
929        Ok(bv)
930    }
931
932    fn octet_string_from_value(value: AvnValue) -> Result<alloc::vec::Vec<u8>, DecodeError> {
933        match value {
934            AvnValue::OctetString(bytes) => Ok(bytes),
935            other => Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
936                needed: "octet string ('...'H)",
937                found: alloc::format!("{other:?}"),
938            })),
939        }
940    }
941
942    fn char_string_from_value(value: AvnValue) -> Result<alloc::string::String, DecodeError> {
943        match value {
944            AvnValue::CharString(s) => Ok(s),
945            AvnValue::OctetString(bytes) => alloc::string::String::from_utf8(bytes).map_err(|e| {
946                DecodeError::custom(
947                    alloc::format!("Invalid UTF-8 in AVN string: {e}"),
948                    crate::Codec::Avn,
949                )
950            }),
951            other => Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
952                needed: "character string",
953                found: alloc::format!("{other:?}"),
954            })),
955        }
956    }
957
958    fn sequence_of_from_value<D: Decode>(
959        &mut self,
960        value: AvnValue,
961    ) -> Result<alloc::vec::Vec<D>, DecodeError> {
962        let items = match value {
963            AvnValue::SequenceOf(items) => items,
964            AvnValue::Sequence(fields) if fields.is_empty() => alloc::vec![],
965            other => {
966                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
967                    needed: "sequence of",
968                    found: alloc::format!("{other:?}"),
969                }));
970            }
971        };
972        items
973            .into_iter()
974            .map(|v| {
975                self.stack.push(Some(v));
976                D::decode(self)
977            })
978            .collect()
979    }
980
981    fn set_of_from_value<D: Decode + Eq + core::hash::Hash>(
982        &mut self,
983        value: AvnValue,
984    ) -> Result<SetOf<D>, DecodeError> {
985        let items = match value {
986            AvnValue::SequenceOf(items) => items,
987            AvnValue::Sequence(fields) if fields.is_empty() => alloc::vec![],
988            other => {
989                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
990                    needed: "set of",
991                    found: alloc::format!("{other:?}"),
992                }));
993            }
994        };
995        items.into_iter().try_fold(SetOf::new(), |mut acc, v| {
996            self.stack.push(Some(v));
997            acc.insert(D::decode(self)?);
998            Ok(acc)
999        })
1000    }
1001
1002    fn choice_from_value<D: DecodeChoice>(&mut self, value: AvnValue) -> Result<D, DecodeError> {
1003        let (identifier, inner_value) = match value {
1004            AvnValue::Choice { identifier, value } => (identifier, value),
1005            other => {
1006                return Err(DecodeError::from(AvnDecodeErrorKind::AvnTypeMismatch {
1007                    needed: "choice (identifier : value)",
1008                    found: alloc::format!("{other:?}"),
1009                }));
1010            }
1011        };
1012
1013        let all_variants = variants::Variants::from_slice(
1014            &[D::VARIANTS, D::EXTENDED_VARIANTS.unwrap_or(&[])].concat(),
1015        );
1016        let tag = all_variants
1017            .iter()
1018            .enumerate()
1019            .find_map(|(i, t)| {
1020                D::IDENTIFIERS
1021                    .get(i)
1022                    .filter(|&&id| id.eq_ignore_ascii_case(&identifier))
1023                    .map(|_| *t)
1024            })
1025            .unwrap_or(Tag::EOC);
1026
1027        if tag != Tag::EOC {
1028            self.stack.push(Some(*inner_value));
1029        }
1030        D::from_tag(self, tag)
1031    }
1032
1033    fn utc_time_from_value(value: AvnValue) -> Result<UtcTime, DecodeError> {
1034        crate::ber::de::Decoder::parse_any_utc_time_string(Self::char_string_from_value(value)?)
1035    }
1036
1037    fn generalized_time_from_value(value: AvnValue) -> Result<GeneralizedTime, DecodeError> {
1038        crate::ber::de::Decoder::parse_any_generalized_time_string(Self::char_string_from_value(
1039            value,
1040        )?)
1041    }
1042
1043    fn date_from_value(value: AvnValue) -> Result<Date, DecodeError> {
1044        crate::ber::de::Decoder::parse_date_string(&Self::char_string_from_value(value)?)
1045    }
1046}